赞
踩
说不清楚,只能看代码理解的用红色标出
查找算法:查找较排序来说较简单,不外乎顺序查找和二分查找、哈希表查找和二叉排序树查找。(很多面试官喜欢让应聘者写出二分查找(如test53)的代码)【注意:二分查找传入的必须是排好序的数组】
排序算法:面试官经常会要求应聘者比较插入排序、冒泡排序、归并排序、快速排序等不同算法的优劣,作者强烈建议应聘者在准备面试时,一定要对各种排序算法的特点烂熟于心,能够从额外的空间消耗、平均时间复杂度和最差时间复杂度等方面取标胶他们的优缺点。(很多面试官喜欢让应聘者写出快速排序、归并排序(test51考察的就是归并排序)的代码)
树的遍历:通常分为两种:深度优先和广度优先。深度优先又细分为三种:前序遍历、中序遍历和后序遍历,对应的程序可以用递归实现,也可以用循环实现(循环实现的方法有点难)。一种有特殊顺序的二叉树称为二叉搜索树。(很多面试官喜欢让应聘者写出红黑树、B+树的代码)
先考虑一般情况,用递归的方式创建二叉树,再考虑特殊的,两种情况:先/中序遍历都是空;先/中序遍历都只有一个节点;
创建好二叉树后,进行特殊情况的测试,两种特殊情况:①根节点为空;②先序遍历和中序遍历序列不匹配;
最后用先序遍历的方式打印一下二叉树(在本代码中遍历二叉树时,会出现空值,可在打印前加个条件语句判断一下,具体原因在demo中有解释)
思路:先根据前序遍历找到根节点,然后再根据根结点的将中序遍历且分为左右两颗子树,再根据子树的长度切分前序遍历,从而切分出小的先序遍历和中序遍历,然后循环以递归的方法解题
题目:给定一颗二叉树和其中的一个节点,找出中序遍历的下一个节点。其中已知该节点的左右子节点和该节点的父节点。
思路:
先在纸上画一颗满二叉树
题目:用两个栈实现一个队列。队列的声明如下,实现它的两个函数appendTail和deleteHead, 分别完成在队列尾部插入节点和在队列头部删除节点。
思路:
这样就通过两个栈构造出了队列。
面试题10:斐波那契数列
题目一:求斐波那契数列的第n项。写一个函数,输入n,求斐波那契数列(Fibonacci)的第n项。(结合第二部分的12,也是斐波那契数列但是多了一种临时变量的解法)
【斐波那契数列:f_0=0, f_1=1, f_2=f_0+f_1=1, f_3=f_2+f_1=1+1=2, f_4=f_3+f_2=2+1=3, 以此类推】
题目二:青蛙跳台阶问题。一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶,求一只青蛙跳上n级台阶总共有多少总跳法。
思路:
题目一:
题目二:
这道题的关键在于怎么把该问题转换为斐波那契数列的问题。
把n级台阶的跳法看作n的函数,记为f(n), 若第一次跳1级,剩下f(n-1); 若第一次跳2级,剩下f(n-2), 所以n级台阶的跳法为f(n)=f(n-1)+f(n-2)
相关题目:用一个2*1的矩形去覆盖2*8的矩形,问有多少种覆盖方法?(类似于unknow3矩形覆盖这个题)
总结(仅供参考):可以转换为斐波那契数列的问题通常具有以下特征:
旋转数组中的最小数字。把一个数组最开始的若干元素搬到数组的末尾,则称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素,如[3,4,5,1,2]为[1,2,3,4,5]的旋转,该数组的最小元素为1.
思路:
矩阵中的路径。设计一个函数用来判断一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵的任意一格开始,每一步都可以在矩阵中向左、右、上、下移动一格。如果一条路径中包含了矩阵的某一格,那么该路径不能进入该格子。【提示:用的是回溯法,回溯法适合有多个步骤且每个步骤都有很多选项的问题,通过遍历式的尝试找到最优的可行方案】
思路:采用回溯法进行解题,每到一个格子都有上下左右四步走法,用循环用第一行第一列的元素开始往下寻找,若该位置的元素等于要寻找的元素时进入递归以查看其上下左右是否能匹配下一个元素,否则返回上一级;其实就是找到首字母后才会进入递归,进一步判断其上下左右是否有符合的,否则重新返回到for循环,寻找下一个匹配成功的首字母。【稍微有点绕】
机器人的运动范围。地上有一个m行n列的格子。一个机器人从坐标(0,0)的位置开始移动,每次可以向左右上下移动一格,但不能进入行坐标和列坐标位数之和大于k的格子。如k=18时,机器人可以进入(35,37), 但不能进入(35,38)。问该机器人能到达多少个格子?
剪绳子。给你一根长度为n的绳子,请把绳子剪成m段(m、n都是整数,m、n>1, 【可知:m的取值范围为大于等于2,小于等于n】),每段绳子的长度记为k[0]、k[1]、k[2]、...、k[m]。请问k[0]*k[1]*k[2]*...*k[m]的最大乘积是多少?例如当绳子的长度为8时,可以剪长度为为2、3、3的三段,此时得到的最大乘积为18。
贪婪算法解题时,为什么是3的k次方,如下图所示:
二进制中1的个数。实现一个函数,输入一个整数,输出该数二进制中1的个数。如9的二进制为1001,有2位是1,因此返回2。
new method
================================================================================================
题目:实现一个函数,输入一个整数,输出该数二进制中1的个数。如9的二进制为1001,有2位是1,因此返回2。(其中负数用补码表示)
思路:
python比较特殊,不管数有多大都不会溢出,所以在此只取前32位(n = 0xFFFFFFFF&n 一个F是4个1)
①将截取的32位数字转换为二进制,再转换为字符串统计1的个数;
②将数字左移统计;
③在while中n=n&(n-1),count+=1, 每次n&(n-1)都会减去二进制中的一个1
数值的整数次方。求base值得整数次方,不得使用库函数,同时不用考虑最大数的问题。
思路:
题目:输入数字n,按顺序打印出从1到最大的n位十进制数。如输入3,,则打印出1,2,3,...,999
思路:关键在于怎么设置循环结束的条件(在其他语言中要考虑大数,防止溢出,但是在python中不用考虑溢出的问题)
题目一:在O(1)时间内删除列表节点,返回最终链表的头节点。给定单向列表的头指针和一个节点指针,定义一个函数在O(1)时间内删除该节点。
思路:
因为最终要返回的是链表的头节点,所以需要借助空间复制一个新的链表,但是新的链表比原链表的在头节点处多一个元素,然后接下来的操作在新链表上进行,最终返回新链表的next。需要借助两个指针用来标记前后位置,如果前面的节点发现了目标节点,则后面的指针指向前面节点的下一个节点,从而实现删除节点;要注意删除节点不存在的情况
题目二:删除链表中的重复节点。在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
思路:
因为最终要返回的是链表的头节点,所以需要借助空间复制一个新的链表,但是新的链表比原链表的在头节点处多一个元素,然后接下来的操作在新链表上进行,最终返回新链表的next。需要借助两个指针用来标记前后位置,先找到重复的节点的值,然后再去删除从该节点起等于删除节点值的节点
题目:请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符"+100"、"5e2"、"-123"、"3.1416"及"-1E-16"都表示数值,但"12e"、"1a3.14"、"1.2.3"、"+-5"、"12e+5.4"都不是
思路:
(反面解题,针对不合规的情况讨论,剩下的就是合规的情况)表示数字的字符串遵循A[.[B]][e|EC]或.B[e|EC],其中A和C都是整数(可以有正负号,也可以没有),而B只能是一个无符号整数找三个辅助变量分别表示正负号、小数点、E/e是否出现或出现的位置是否合适。遍历整个字符串,每个字符进行判断, 正负号只能出现在整数部分的前面或者是e/E的后面;小数点只能出现一次, 且在e/E的部分不能出现小数;e/E只能在数字的后面且其前面不能没有数字,且只能出现一次
题目:输入一个整数数组,实现一个函数调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于后半部分。
思路:
变体:
面试题22:链表中倒数第k个节点
面试题22:输入一个(单向)链表,输出该链表中倒数第k个节点。如链表为[1,2,3,4,5], k=2时,输出倒数第二个节点为4
思路:
题目:给定一个链表,若其中包含环,请找出该链表的环的入口节点,否则输出null
思路:
证明过程如下(假设链表中有环):
假设s与f第一次相遇时,s已经走了l步,则f走了2l步;
假设入环前的步长为a,s进环后与f相遇又走了b步,则l=a+b,相遇的位置距离环的入口为c;
则f所走的步长2l=a+n*(b+c)+b, 其中n表示f在环中所绕的圈数
有2*(a+b)=a+n*(b+c)+b, 化简得a=c+(n-1)*(b+c),(其中b+c表示环的长度)
题目:定义一个函数,输入链表的头节点,反转该链表并输出反转后链表的头节点。(就是要求把一个单向链表有正序变为倒序)
思路:
题目:输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是按递增排序的。输出合并后的链表
思路:
建立一个新的链表,找两个游标作为标记, 再找一个指针指向新链表的前一个节点,每次两个游标进行比较从而判断指针的下一个节点
题目:输入两颗二叉树A和B,判断B是不是A的子结构(注意:约定空树不是任意树的子结构)
思路:
主要是分为三种情况处理:第一种,二者的根节点就相同;第二种,B是A的左子树的一部分;第三种,B是A的右子树的一部分;针对每一种情况再判断B是否是A的子结构(如何判断:先判断根节点是否相等,如果相等,再分别去判断左、右两边是否相等,整体相等才能返回True,否则只能返回false)
题目:请完成一个函数,输入一个二叉树,该函数输出它的镜像
思路:
采用递归的方式,每次对调根节点下的左右子节点
题目:请实现一个函数,用来判断一颗二叉树是不是对称的。如果一颗二叉树和它的镜像一样,那么它就是对称的,否则不是
思路:
采用递归的方法,判断左子树的左边是否与右子树的右边相等,左子树的右边是否与右子树的左边相等
题目:定义栈的数据结构,在栈的原有功能上添加一个能够得到栈的最小元素的min函数,要求:在该栈中,调用min、push及pop的时间复杂度都是O(1)
思路:
题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字都不相等。例如1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。
思路:
每压入一个元素,都会考虑弹出或不弹出的情况,不弹出则继续压入;弹出则弹出,下一个元素接着考虑是否弹出,不弹出则压入,由此得到第二个序列,即第二个序列是出栈方式中的一种可能结果
题目:从上往下打印出每个二叉树的节点,同一层的节点按照从左到右的顺序打印
思路:
将树的每一个左右节点都按照左右的顺序放入队列中,然后再按照先进先出的顺序打印出该节点的值,再将它的左右子节点放入队列中
题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则返回True,否则输出False。假设输入数组的任意两个数字都互不相同
(名词解释:二叉搜索树————左子树的值必然小于根节点,右子树的值必然大于根节点的值;或者是一颗空树)
思路:
二叉搜索树的后序遍历,如5 7 6 9 11 10 8,8是根节点,根据二叉树的性质判断出5 7 6 是左子树的(都小于8),9 11 10是右子树的(都大于8),再递归进行判断,如果应该是右子树的部分出现小于根结点的(如小于8),则输出False
题目:输入一颗二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点往下一直到叶节点所经过的结点形成一条路径
(注意:第一,路径指的是从根节点到叶子节点的一条完整的路径)
思路:
根据广度优先的方法,依次去寻找路径和为输入整数的路径(看代码吧,不太明白)
题目:输入一颗二叉搜索树,将该二叉搜索树转换为一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向
思路:
参考网址:https://blog.csdn.net/u010005281/article/details/79657259作者讲的很详细。
借用两个辅助变量分别标记双向链表的头节点和尾节点,按照中序遍历的思路,用递归进行解题。尾部节点得每次移动到尾部,从而每次都是尾部标识。
题目:请实现两个函数,分别用来序列化和反序列化二叉树
思路:
序列化的过程就是对树进行前序遍历,但是要注意找一个记号(如'#')标记叶子结点;
反序列化的过程将序列转换为树结构。先将字符串且分为列表格式,再根据所做的叶子结点的标记采用递归的方法,找出左右子节点从而还原为一棵树
面试题38:字符串的排列(所有字符串可能的排列组合)
题目:输入一个字符串,打印出该字符串中字符的所有排列。例如,字符串a、b、c所能排列出的所有字符串有abc、acb、bac、bca、cab和cba
思路:
看不懂,死记吧
题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如一个输入长度为9的数组{1,2,3,2,2,2,5,4,2}, 由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2(注意:这个题主要考察的是时间复杂度和空间复杂度)
思路:
题目:输入n个数,找出其中最小的k个数。例如,输入4 5 1 6 2 7 3 8这8个数字,则最小的4个数字是1 2 3 4
(这个题主要是考察时间复杂度;知识点:最大最小堆)
提示:找k个最小的数,需要用到最大堆;找k个最小的数,需要用到最小堆;最大最小堆必须是一个完全二叉树;堆插入一个值的时间复杂度为O(lgn), 删除一个
值得时间复杂度为O(lgn), 创建一个堆的时间复杂度为O(n); 完全二叉树找到其父节点的索引的公式为(index-1)//2,index为当前值的索引,注这里的索引顺序是
按照广度优先排序的,反过来也可以找到其子节点,左子节点索引为index*2+1, 右子节点索引为index*2+2,
思路:
题目:
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值,如果数据流中读出偶数个数值,那么中位数就是所有数值排序后中间两个数字的平均值。我们使用insert()方法读取数据流,使用getMedia()方法获取当前读取数据流的中位数
思路:
将数组里的数交替放入最大堆最小堆中,这样中位数只能是最大堆的堆顶或者最大最小堆堆顶元素的均值。首先编写最大堆最小堆的创建及修改的函数(共4个),交替的往最大最小堆添加数字(添加数字的过程是重点),从而保证最大最小堆里的元素个数要么相等,要么相差一个,从而实现了实时获取数据流的中位数。
题目:输入一个整型数组,数组里有正数也有负数。数组中一个或连续的多个整数组成一个子数组,求所有子数组和的最大值。例如,{6,-3,-2,7,-15,1,2,2}, 连续子向量的最大和为8(从第0个开始到第三个为止)。要求时间复杂度为O(n)【题目的意思是找出连续的数字中那几个加起来是最大的,只需要找到子数组和最大的那个和就行,不需要找出子数组】
思路:
找两个辅助变量,一个记录最大和,另一个记录加到第i个数之前的和,通过遍历数组,从而找到连续子数组的最大和
题目:输入一个正整数n,求从1到n这n个整数的十进制表示中1出现的次数。例如输入12,从1到12这些整数中包含1的数字有1,10,11和12,1一共出现了5次
(这道题主要是考察时间复杂度)
思路:
题目:数字以012345678910111213141516……的格式序列化到一个字符序列中,在这个序列中,第五位(从0开始计数)是5,第十三位是1,第十九位是4等。写一个函数,求任意n位对应的数字。
思路:
题目:输入一个正整数数组,把数组里面所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如,输入数组{3,32,321},则打印出这3个数字能排成的最小数字321323(321 32 3)
思路:
(有点类似于面试题38————字符串的排列,n个数字共有n!种排列,但是如果使用这种方法的话,还是很慢)
参考网址:https://blog.csdn.net/u010005281/article/details/80085476
使用了快排的思路,但是不太理解,和书上讲的那一长串有点不一样
题目:给定一个数字,我们按照如下规则把它翻译为字符串:"0"翻译为"a","1"翻译为"b","2"翻译为"c",……,"25"翻译为"z"。一个数字可能有多个翻译。例如,"12258"有五种不同的翻译,分别是"bccfz"、"bwfi"、"bczi"、"mcfi"、"mzi"。写一个函数,计算一个数字有多少种不同的翻译。
思路:
采用递归的思路, 从后往前或从前往后,依次判断一位与两位(两位数必须小于26才行),有点类似于斐波那契数列递归的方法f(n)=f(n-1)+f(n-2)
6
5 25
2 12 1 11
1 11 1 1
1
题目:在一个m*n的棋盘的每一格都放一个礼物,每个礼物都有一定的价值(价值大于0).你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下
移动一格,直到到达棋盘的右下角。给定一个棋盘及其上面的礼物,请计算你最多拿到多少价值的礼物
思路:
动态规划。(看不明白,还是看代码死记)
参考网址:https://www.jianshu.com/p/71bc21981090
变体:礼物的最大价值及其取得最大价值的路径
题目:请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度,假设字符串中只包含"a"~"z"的字符。例如,在字符串'arabcacfr'中,最长的不含重复字符的子字符串为acfr,长度为4
思路:
题目:把因子只包含2、3、5的称为丑数(ugly number)。求按从小到大第N个丑数,例如6、8都是丑数,但是14不是,因为它的因子包含7,习惯上把1当做
第一个丑数(注意:主要考虑时间复杂度)
思路:
题目一:字符串中第一个只出现一次的字符。在字符串中找出第一个只出现一次的字符。如输入"abaccdeff",则输出'b'
思路:
题目二:字符流中第一个只出现一次的字符。写一个函数,找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g";当从该字符流中读出前6个字符"google"时,第一个只出现一次的字符是"l"
思路:
可以根据题目一的思路改一下即可,每输入一个数据流字符串,都判断一下当前第一个出现的子字符串,为了避免每次重复计算,可以将字典和列表定义在类下的init中
题目:在数组中的两个数字如果前面一个数字大于后面一个数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。例如,{7,5,6,4}中,一共有(7,5), (7,6), (7,4), (5,4), (6,4) 5个逆序对(注:输入的数组中没有相同的数字)
思路:
题目一:数字在排序数组中出现的次数。统计一个数字在排序数组中出现的次数。例如,输入排序数组{1,2,3,3,3,3,4,5}和数字3,由于3出现了4次,所以输出4
思路:
题目二:0~n-1中缺失的数字。一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字范围都在0~n-1之内。在范围0~n-1内的n个数字中,有且只有一个数字不再该数组中,请找出这个数字。
思路:
题目:给定一颗二叉搜索树,请找出其中第k个最小结点值(书上的意思还是找出第k个最小值)。例如(5,3,7,2,4,6,8)中,按结点数值大小顺序第三小结点的值为4(补充:二叉搜索树:左子树都小于父节点,右子树都大于父节点)
思路:
等价于中序遍历找第k个值,先对给定的二叉搜索树进行中序遍历,将序列放于列表中,再去寻找是否有第k个元素
题目一:二叉树的深度。输入一颗二叉树的根节点,求该树的深度,从根节点到叶节点依次经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度为树的深度。
思路:
参考网址:https://blog.csdn.net/dailu11/article/details/80609416?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task
自己做不会,但是一看别人的(哦,好像是那么回事;对递归理解还是不到位)
题目二:平衡二叉树。输入一颗二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树深度相差不超过1,那么它就是一颗平衡二叉树
思路:
根据二叉树深度的思路,判断其左右子树的最大深度并进行比较,如果大于1,直接返回False,否则再进一步判断其子树是否满足, 这种方法每个节点只需要遍历一次即可
题目:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n), 空间复杂度是O(1)(这个题目比较难,难以口述清除,要结合代码进行理解)
思路:
使用异或这个位运算进行解题(首先异或运算也具有交换律)。
因为数组中除了两个只出现依次的数字外,其他的数字都是出现了两次,使用异或运算可以使出现两次的数字的异或结果为0(如(1,1,2,2,3,4,4,5,5,6), 整体进行异或后,结果为5==101),从而找出两个只出现一次数字的异或结果x,再找到x的二进制码中1首次出现的位置,并截取其右半段为y(如5的右半段为1,再如异或结果为20==10100,截取的右半段为100);再用截取的右半段y与数组中的每个数字进行与操作,可以将数组分为两段,并且每段中有一个只出现一次的数字,再分别对每段进行异或操作,从而找到了两个只出现一次的数字
题目一:和为s的两个数字,输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得他们的和正好是s。如果有多对数字和胃s,输出任意一对即可。
思路:
找两个指针,一个指向头,一个指向尾,从而去找s,这样的时间复杂度为O(1)
题目二:和为s的连续正数序列。输入一个正数s,打印出所有和为s的连续正数序列(至少含有两个数)。例如,输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以打印出3个连续序列1~5、4~6和7~8
思路:
找两个指针,指向1和2,如果cur1到cur2的和小于targetSum,那么cur2加1;如果大于targetSum,则cur1加1;等于,则记录下来,cur2加1,循环判断直到没有为止(终止条件:cur1的值小于(1+targetSum)/2时一直满足条件)
题目一:翻转单词顺序。输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如,输入字符串"I am a student.",则输出"student. a am I"
思路:
先切分开,翻转后再用空格链接回去
题目二:左旋转字符串。字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。例如,输入字符串'abcdefg'和数字2,该函数将返回左旋转两位得到的结果'cdefgab'
思路:将前面的n个字符串移动到后面即可
题目一:滑动窗口的最大值。给定一个数组和滑动窗口,请找出所有滑动窗口的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一个存在6个滑动窗口,它们的最大值分别为{4,4,6,6,6,5}
思路:
题目二:队列的最大值。请定义一个队列并实现函数max得到队列里的最大值。要求函数max、push_back、pop_front的时间复杂度都是O(1)
思路:(没整明白题目是什么意思)
题目:把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s的所有可能的值出现的概率
思路:
动态规划问题。f(n, s) = f(n-1, s-1) + f(n-1, s-2) + f(n-1, s-3) + f(n-1, s-4) + f(n-1, s-5) + f(n-1, s-6)。初始条件,f(1,1)=f(1,2)
=f(1,3)=f(1,5)=f(1,6)=1
参考网址:https://www.bbsmax.com/A/1O5EVXAWd7/
题目:从扑克牌中随机抽5张牌,判断是不是一个顺子,即这五张牌是不是连续的,A为1,J为11,Q为12,K为13,而大小王可以看作任意数字。
思路:
大小王可以看成是任意数字,假设为0。先对数组进行排序,然后统计0的个数,再统计连续数字出现间隔的个数,如果0的个数大于等于出现间隔的个数,则可以认为是连续的;否则,认为是不连续的
题目:0,1,...,n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字,求出这个圆圈里剩下的最后一个数字。如0,1,2,3,4这五个数字组成一个圆圈,从0开始每次删除第三个数字,则删除的前四个数字依次是2、0、4、1,因此最后剩下的数字是3
思路:
题目:假设把某股票的价格按照时间先后顺序存储在数组里,请问买卖该股票一次可能获得的最大利润是多少?例如,一只股票在某些时间节点的价格为{9,11,8,5,7,12,16,14}。如果我们能在价格为5的时候买入并在价格为16时卖出,则能收获的最大利润是11
思路:
(实际上是找数组的最大差值)
题目:求1+2+……+n,要求不能用乘除法、for、while、if、else等关键字及条件判断语句
思路:
发散性思维,在实际中不太可能出现。
题目:写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号(这个题只能死记,技巧性太强)
思路:
进行位运算,进行按位与、异或运算
将十进制数转换为二进制,
第一步,先进行两者间先进行按位与运算,如果结果为0,那么二者再进行的异或结果转换为十进制就是最终结果;
第二步,如果按位与结果不为0,说明有地方需要进一位,对其右补一位0并记为x(左移1位),原来的两者间进行异或操作得到y;第三步,将x与y重复前面的步骤
题目:给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中B中的元素B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1]。不能使用除法
思路:
- # 限制数字的范围[-2^32, 2^32-1],超过范围则返回左或右区间值;首字符不为'+'、'-'、' '时,直接返回0;
- # 当首次遇到字母时直接返回当前已经得到的数
- # 思路:借助三个辅助变量用来记住正负号、当前的数字、for循环遍历开始的位置,res=10*res+(ord(strs[i])-ord('0'))
题目:请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三层按照从左到右的顺序打印,依次类推
思路:
①(行不通)按照广度优先的思路执行不通,因为很难区分清楚打印到第几层,从而没办法及时调整方向(从左到右还是从右到左)
②找两个栈,将奇数层的结点从右到左append进去,将偶数层的结点从左到右append进去,最后再从尾部pop出来
题目:从上到下打印二叉树,同一层结点从左到右输出,每一层输出一行
思路:
与上一个按之字形打印二叉树的题目高度相似,只是把上一个题用的栈换为队列
题目:用2*1的小矩形横着或竖着覆盖更大的矩形,请问用n个2*1的小矩形无重叠的覆盖一个2*n的大矩形,总共有多少种方法
思路:
原理就是斐波那契数列,如果第一块是竖着放的,那么剩下的就相当于n-1的情况,如果第一块是横着放的,那么第二块的方法就确定了,就相当于是n-2的情况
水平线以上的是剑指offer的题,水平线以下也是算法题(但不是剑指offer上的)
洗牌问题。用Array编写洗牌问题?如何测试?(一个好的洗牌是每一张牌出现在一个地方的概率是相同的)
解题方法:
题目:计算质数。给一个数n,返回它里面的所有质数的个数;如17,它的质数个数为7(包含17),则返回7。
思路:
注意:
题目:证明巴德赫猜想。任意大于2的偶数都可以写成两个质数(素数)之和,如16=3+13。(这道题换句话表达:将任意一个大于2的偶数表示为两个质数之和)
思路:
注意:
题目:扫雷游戏。程序接收三个参数M,N,p,然后生成一个M*N的矩阵每一个cell都有p的概率是地雷,生成矩阵后,然后再计算每一个cell周围地雷的数量。
思路:
题目:矩阵0变换。给定一个m*n的矩阵,如果有一个元素为0,则把该元素对应的行和列全部转换为0
思路:
题目1:九宫图(与数独规则不一样)。每一行每一列以及对角线的元素加起来和相等(注:九宫图的行数与列数必然为奇数)
思路:
注意:
题目2:数独。在9*9的格子里,每一行每一列以及每一个切分好的3*3的格子里,1~9都仅出现一次。给一个填好的数独,验证其是否正确。
思路:
题目:旋转数组。给定一个n*n的数组,将其顺时针旋转90度。
思路:
参考网址:https://blog.csdn.net/shahuzi/article/details/97825167
题目:反转字符串
思路(这个题目还是很简单的):
题目:最长连续子串。给定一个只包含0和1的数组,找出只包含1的最长子串。
思路:
题目:最大数。给定一个数组,数组里有且只有一个最大数,判断这个数是否是其他数的两倍或更大,如果存在这个数,则返回其index,否则返回-1
注意:
思路:
题目:找到数组中消失(没有出现)的数。给定一个长度为n的数组,里面数字的范围为[1,n],有的数字出现了多次,有的一次也没有出现,找到没有出现的数字。要求:不能占用其他的空间,时间复杂度不鞥超过O(n)
思路:
注意:
思路(3种方法):
题目:打印对称的尺子。如n=1时,输出1;n=2时,输出1 1 2 1;n=3时,输出1 1 2 1 1 2 1 3 1 2 1;n=4时,输出1 1 2 1 1 2 1 3 1 2 1 1 2 1 3 1 4 1 3 1 2 1;……
思路:
题目:数学表达式。给定a和b两个数,a<=b,把b以a乘2或者加1的最快的方式表示出来。(只能在a的基础上乘2或者加1)
思路:主要分析b>2a以及b%2=0是否成立, 当b<2a时,只能通过加1达到b,当b为奇数时通过加减1使b变为偶数
题目:(重要)找出一个集合的所有子集。打印出来即可。(leetcode上的:https://leetcode-cn.com/problems/subsets/)
思路:
变体:该集合中有重复的元素(可以直接用set去重)。
16、寻找旋转有序数组的最小值
这个题和剑指offer上的那一道一样,本文上面也有,这次的解题代码
变体,题目二:在旋转的有序数组中寻找某个值。【有难度】
思路:
17、搜索插入位置
题目:给定有序数组和一个目标值,如果在数组中找到此目标值则返回与目标值相等的值的index,如果没有找到,则返回目标值按顺序应该被插入的位置。(注:假设该数组中不存在重复数)
思路:有点类似于插入排序。
实际上就是找到第一个大于等于item的数的位置,没有找到则放在最后的位置上
18、搜索一个重复数字的区间
题目:搜索一个区间。给定一个排好序的有重复数字的array,找到一个给定目标值的起始位置和结束位置。如果都没有,返回(-2,-2)
思路:
就是先找到第一次出现的位置,再找到第二次出现的位置。【用的是18中的经典二分搜索的方法】
这种解法的时间复杂度为log(n)+log(n),用for从头到尾遍历的时间复杂度为O(n)
19、在有空字符串隔开的有序array中查找元素
题目:在有空字符串隔开的有序array中查找元素。给定一个有序的字符串序列,这个序列中的字符串用空字符串隔开,请写出找到给定字符串位置的方法。如[' ', ' ', 1, ' ', ' ',' ', 2, ' ',3]
思路:
题目:求出两个序列(或数组)中的公共子序列的个数,其中公共子序列可以不连续,但是是有顺序的【是leetcode的1143题,重点题目★★★】
思路:
- 动态规划问题,array[i][j]表示s1序列的前i个元素、s2序列的前j个序列的公共子序列数量,
- # 当i=0或j=0时,array[i][j]=0;
- # 当x_i=y_j时,array[i][j]=array[i-1][j-1]+1;
- # 当x_i不等于y_j时,array[i][j]=max(array[i-1][j],array[i][j-1])
思路:方法有很多种,如二分法、拟牛顿法等。这里的解法是二分法:设置一个区间[left, right],left初始化为0,right初始化为num,如果num小于1,则令right=1;然后根据abs(mid^2-num)大于小于或等于0.001来进行调整区间,从而在满足一定精度的情况下返回最终值。
思路:先对列表里的数进行排序,再找三个指针,cur1是跟着for循环变化,cur2、cur3是动态变化
思路:这道题的路径的起始点可以是任意节点(只要不违背前、中、后序遍历的原则即可);相关题目是test34二叉树中和为某一值的完整路径
题目:找出数组中每个元素距离最近的0的步长,只能是上下左右行走
思路:有两种解题方法,一是图论中的广度优先搜索方法(不懂图论);二是动态规划进行解题,因为考虑到是上下左右,所以先从左上角执行一遍,最后再从右下角执行一遍,从而达到上下左右,先定义一个dp函数,避免重复写动态规划
题目:输入一个序列,找到其所有的回文子序列(这里的回文子序列可以不连续)
思路:动态规划,先列出转移方程,再解决问题。 d[i][j]表示s[i]……s[j]间的最长回文子序列数量,当i=j是,d[i][j]=1; 当i不等于j时,d[i][j]=max{d[i+1][j], d[i][j-1]} # 相关题目:最长公共子序列
相关题目:leetcode5最长回文子串,这道题目中要求的是回文子串是连续的
思路:不断取数组的第一行放入结果列表中,每放一次,就把剩下的数组逆时针旋转90度,以把最后一列变为新数组的第一行,然后接着把第一行pop出来放入结果列表中
参考网址:https://blog.csdn.net/Lynette_bb/article/details/73414119
相关题目:旋转数组,将一个数组旋转90度(第7个)
27、leetcode977有序数组的平方及变体求出有序数组中平方中不同的值的个数
思路:输入一个有序数组,要求返回的平方也是有序的,注意处理平方和相同的情况;
它的变体与之解决办法类似,只是稍微有些改动(完整代码有些长35行左右,但是思路还是挺简单,就是要处理各种特殊情况比较复杂点)
题目路径:1109. 航班预订统计
方法一:双循环暴力解决,但是时间复杂度为O(n^2),无法通过;
方法二:差分法(模拟公交上下车),这样的时间复杂度为O(n*m),空间复杂度为O(1)
题目路径:leetcode17电话号码的字母组合
解题思路:有点类似与字符串的所有子集
题目路径:leetcode单词拆分
思路:动态规划的问题,dp[i]表示s[0:i]的字符串是否可拆分
题目路径:leetcode重复DNA序列
思路1:使用list,遍历字符串,但是无法通过时间复杂度;
思路2:改用set,遍历字符串,可以通过时间复杂度。
题目路径:打家劫舍(leetcode198)
思路1:使用递归的方式解题,但是无法通过时间复杂度;
思路2:动态规划,dp[i]表示前i-1间房子的最大收益,dp[i]=max(dp[i-1],nums[i]+dp[i-2])
测试用例:[2,1,1,2]
题目路径:打家劫舍2,此时的房子是一个环形,即首尾不能同时都光顾;
思路:既然首尾都不能光顾,那就比较分别首、尾去掉时所能获得的最大收益。
题目如下:
给定一个数组,它的第i个元素是一支给定的股票在第i天的价格。设计一个算法来计算你所能获取的最大利润。你最多可以完成两笔交易。注意:你不能同时参与多笔交易(你必须在再次购买之前出售掉之前的股票)。
example1:输入[3,3,5,0,0,3,1,4] 输出:6
解释:在第4天(股票价格=0)的时候买入,在第6天(股票价格=3)的时候卖出,这笔交易所能获得利润=3-0=3.随后,在第7天(股票价格=1)的时候买入,在第8天(股票价格=4)的时候卖出,这笔交易所能获得利润=4-1=3。
example2:输入[1,2,3,4,5] 输出:4
解释:在第1天(价格=1)的时候买入,在第5天(价格=5)的时候卖出,这笔交易所能获得利润=5-1=4.注意你不能在第1天和第2天接连购买股票,之后再将它们卖出。因为这样属于同时参与了多笔交易,你必须在再次购买之前出售掉之前的股票。
example3:输入[7,6,4,3,1] 输出:0
解释:在这个情况下,没有交易完成,最大利润为0
思路:类似于差分法(29、航班预定统计(leetcode1109);33、打家劫舍(leetcode198)),先计算相邻两天的交易的收益,再计算连续相邻正数的和(因为是正数,说明交易可以获取收益,通过连续正数,从而获得这笔交易的最大收益)
相关题目:股票的最大利润(仅交易一次)【剑指offer63或leetcode121】
35、去除重复字母
思路:借用栈、字典可以解题,方法还是比较巧妙的。
36、火柴拼正方形
思路:深度优先算法(递归)+遍历每个数组的每个元素,有点难
37、子域名访问计数
思路:遍历+split,此题比较简单
38、有效的数独
思路:
首先数独自己的特征:①同一行无重复数字1-9;②同一列无重复数字;③9个33的格子中无重复数字。所以一共有27组需要验证;
然后从对角线(9个元素)开始,每次遍历并验证对应的行、列以及第i个33的格子是否满足,只要有一个不满足直接return False
39、递减元素使数组呈锯齿状
思路:本题的隐性要求:①只能使用减法变动元素,从而满足条件;②要比较奇数或偶数位置,这两种可能的情况满足要求时的最小变动;(奇数位置的元素都小于偶数位置的元素,或者偶数位置的元素都小于奇数位置元素)【解法还是比较巧妙的】
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。