1 : 给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。
思路:两重循环就可
2. 给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。请你将两个数相加,并以相同形式返回一个表示和的链表。
思路:创建一个新的头节点,两链表相加之和放在新的节点中,并链在此头结点之后,形成新的代表和的输出链表。每次相加,都要确定和是否大于10---dec代表相加之和,对10取余放在新列表对应节点中,对10取整,加在下一次两链表之和中;即,只要两链表下一节点不全为空,或下一节点为空,但当前节点所加大于10,都需要创建新的节点。
3. 将一个给定字符串 s
根据给定的行数 numRows
,以从上往下、从左到右进行 Z 字形排列。比如输入字符串为 "PAYPALISHIRING"
行数为 3
时,排列如下:
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"
。
官方
my:
思路:先创建一个二维数组(大小可根据给定的S的长度及规定的行数确定)。当在第一列时,挨个取出S中元素放到第一列中的每行,列数+1。然后判断当前列数+1是否=numsrow;若不等于,行数从倒数第二循环到1处,放一个s[k]在每行中,行数-=1。直到k !<len(s)
4. 给你一个 32 位的有符号整数 x
,返回将 x
中的数字部分反转后的结果。如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1]
,就返回 0。
思路: 先判断当前数是否超过范围。若在范围内,定义一个列表,先append符号位,注意先对x取绝对值,在以x对10取余,余数依次append进列表,当前数每次对10取整 减小。于是列表中就以逆序得到此数的各个位上的数字。最后从列表尾部开始,每个元素乘上10的对应次方相加即可。最后加上列表下标 0 处的正负号。
5. 字符串转换整数 (atoi):请你来实现一个 myAtoi(string s)
函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C++ 中的 atoi
函数)。函数 myAtoi(string s)
的算法如下:
读入字符串并丢弃无用的前导空格
检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。
读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。
将前面步骤读入的这些数字转换为整数(即,"123" -> 123, "0032" -> 32)。如果没有读入数字,则整数为 0
。必要时更改符号(从步骤 2 开始)。
如果整数数超过 32 位有符号整数范围 [−231, 231 − 1]
,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −231
的整数应该被固定为 −231
,大于 231 − 1
的整数应该被固定为 231 − 1
。
思路: 正则表达式
6. 给你一个整数 x
,如果 x
是一个回文整数,返回 true
;否则,返回 false
。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
例如,121
是回文,而 123
不是。负数永远不是
思路: 将X各个位数拆开放在列表中,头尾开始判断是否一致即可
7. 给定一个长度为 n
的整数数组 height
。有 n
条垂线,第 i
条线的两个端点是 (i, 0)
和 (i, height[i])
。
找出其中的两条线,使得它们与 x
轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:你不能倾斜容器。
思想: 容量由最短板决定
8. 整数转罗马数字
思想: 传进一个数x,先判断x在哪个区间内,再判断由几个一千,几个一百,几个十,几个1组成。再在对应区间内 将x的各个位数上的数字 转化为对应罗马数字。
9.
思想:挨个判断罗马字即可
10 . 编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 ""
。
思想: 先找到列表里最短的字符串,计算其长度,作为外层循环的控制条件。内层循环挨个遍历列表元素(字符串),通过外层指针比较每个字符串的相同位置是否相同。 注意结束循环判断:只要不相等,立刻结束内外两层循环。通过变量 b 将结束信号传递给外层。
11.
给你一个整数数组 nums
,判断是否存在三元组 [nums[i], nums[j], nums[k]]
满足 i != j
、i != k
且 j != k
,同时还满足 nums[i] + nums[j] + nums[k] == 0
。请
你返回所有和为 0
且不重复的三元组。
注意:答案中不可以包含重复的三元组。(难点所在)
思路:双指针; 先排序,后找。两层循环:外层控制循环次数及一个值不动,内层循环在这个值后面从两端(因为有序)开始找。
12.
给你一个长度为 n
的整数数组 nums
和 一个目标值 target
。请你从 nums
中选出三个整数,使它们的和与 target
最接近。
返回这三个数的和。假定每组输入只存在恰好一个解。
思路 ;与上题大致相同, 主要是判断当前三个数 之和与下一个三个数之和 哪一个与target更近。三重循环超过时间。所以双指针
point: 指针k 和 j 的移动
13.给你一个由 n
个整数组成的数组 nums
,和一个目标值 target
。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]]
(若两个四元组元素一一对应,则认为两个四元组重复):
思路: 类似于以上两题;采用排序 后双指针的解法
14. 给你一个链表,删除链表的倒数第 n
个结点,并且返回链表的头结点
喜提创建头节点的方式 :dum=ListNode(0,head) :创建一个头结点,赋值0 并将next指向原本链表的头
思路 : 计算原本链表的长度,删除倒数第n个就是顺数第length-n+1个。
创建一个头结点并链到原本的链表上,找到待删除节点的前一个。删除即可。注意返回的是不带此头结点的链表
15. 给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串 s
,判断字符串是否有效。有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
思路: 栈:遇到左括号 则进栈;遇到右括号,先判断栈是否为空;再判断栈顶元素是否匹配.,若为空或不匹配直接False;若不为空且匹配,删除栈顶元素。
26. 给你一个 升序排列 的数组 nums
,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 .
* 思想 :由于有序,相同的数字连续出现。 双指针法: 一快一慢,i 定位到与前面元素值相同的下标,j 找到与前面值不同的下标。若j 所指元素与前面元素值不同,则将j所指值 给i下标处,i,j同时后移;若j所指元素与前面元素值相同,i不动,j后移。
27. 给你一个数组 nums
和一个值 val
,你需要 原地 移除所有数值等于 val
的元素,并返回移除后数组的新长度。不要使用额外的数组空间,你必须仅使用 O(1)
额外空间并 原地 修改输入数组。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
思想:同上题,双指针法:i,j从0开始,若是val,j+=1,知道找到!=val的值,传递给i所指位置,i,j往后移;若不是,j的值给i,j+=1,i+=1 i,j之间的位置 都是可用的
28. 给你两个字符串 haystack
和 needle
,请你在 haystack
字符串中找出 needle
字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle
不是 haystack
的一部分,则返回 -1
。
思想:利用切片:找到从前往后遍历haystack,判断从当前位置开始,到与needle
字符串长度相同的位置,子集是否与needle相同,若相同,返回当前位置;若不同,当前位置往后移
29 . 给你两个整数,被除数 dividend
和除数 divisor
。将两数相除,要求 不使用 乘法、除法和取余运算。整数除法应该向零截断,也就是截去(truncate
)其小数部分。例如,8.345
将被截断为 8
,-2.7335
将被截断至 -2
。返回被除数 dividend
除以除数 divisor
得到的 商 。
注意:假设我们的环境只能存储 32 位 有符号整数,其数值范围是 [−231, 231 − 1]
。本题中,如果商 严格大于 231 − 1
,则返回 231 − 1
;如果商 严格小于 -231
,则返回 -231
。
思想(位运算): 采用依次减去被除数统计次数的方式 会超过时间限制。故 采用 位运算的方式。除数左移一位(python位运算自动当做二进制进行),相当于扩大两倍,移两位,扩大四倍。从允许最大位数开始移动,为防止除数左移越界,将被除数右移缩小。
30. 给定一个字符串 s
和一个字符串数组 words
。 words
中所有字符串 长度相同。s
中的 串联子串 是指一个包含 words
中所有字符串以任意顺序排列连接起来的子串。
思想: 哈希表 :用collections里的Counter方法,能够统计出列表里的元素及其对应数量。在挨个提取出相同长度的子字符串,以固定长度append进一个列表;在对子字符串同样 Counter方法,统计出其中各个单词及其数量,判断两个是否相等,若相等,返回子串在s中的首字符位置即可。
31. 整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。
- 例如,
arr = [1,2,3]
,以下这些都可以视作arr
的排列:[1,2,3]
、[1,3,2]
、[3,1,2]
、[2,3,1]
。
- 例如,
arr = [1,2,3]
的下一个排列是[1,3,2]
。 - 类似地,
arr = [2,3,1]
的下一个排列是[3,1,2]
。 - 整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。
思想:要点在与 下一个字典序更大的排列。从后往前找,找到一个位置i的值比它前面的值小,而后再次从最后面往前,找到一个值比它大,交换位置。而后让i后面的倒序。
38. 给定一个正整数 n
,输出外观数列的第 n
项.「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。
思想: 双指针 : 后一项 由前一项决定;由给出的n控制循环次数,后将两个指针 从前一项第一位出发,快指针在小于前一项长度的前提下,往后找与慢指针不同的字符,若相同,继续往后,若不同,则停,计算与慢指针的距离,并转换成字符串+慢指针所指元素,存入变量cur;双指针再继续往后找。 最后快指针到前一项最后位置,所形成的cur即为前一项的后一项。
41. 给你一个未排序的整数数组 nums
,请你找出其中没有出现的最小的正整数。请你实现时间复杂度为 O(n)
并且只使用常数级别额外空间的解决方案。
思想: 要找最小的 未出现的正整数;所以在排序后,负数直接跳过;首先判断最小正整数1 在不在nums中,若不在,直接返回1;若在,定位到1的下标 index处,并从这个位置开始,判断后一项与前一项的差值 是否<=1,若是 则连续,指针继续往后,直到倒数第二个 ;否则,两数之间存在其他正整数,直接返回前一个数+1的结果;若到最后一个也连续,则返回最后一个数+1
48.旋转图像:给定一个 n × n 的二维矩阵 matrix
表示一个图像。请你将图像顺时针旋转 90 度。
你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。
思想: 观察 旋转前后的不同,发现规律,代码实现即可
策略: 先上下反转,再对角线反转
49 字母移位词分组:给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。字母异位词 是由重新排列源单词的字母得到的一个新单词,所有源单词中的字母通常恰好只用一次。
思想: 哈希表思想。从列表的第一项开始,若这个元素没有被归到哪一类中,则将它收进一个列表,通过 Counter函数 计算这一项里的字符及对应数量;再从这一项后挨个遍历,先判断遍历到的每一项有没有被收到列表里,若没有,则通过Counter计算字符及数量,若与那一项相同,则加入到那一项所在列表,并标记这一项,接着往后。
56 . 以数组 intervals
表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi]
。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。
思想:先按照每个子列表的首个元素排序;再 慢指针指到一个元素,快指针判断其后的元素是否能与慢指针所指元素合并,若可以,则更新慢指针所指;慢指针在往后移
59 . 螺旋矩阵2. 给你一个正整数 n
,生成一个包含 1
到 n2
所有元素,且元素按顺时针顺序螺旋排列的 n x n
正方形矩阵 matrix
。
思想: 按照 规则,从从左到右,在从上到下,在从右到左,在从下到上,再以此循环填入递增的数字即可
60 排列序列:
给出集合 [1,2,3,...,n]
,其所有元素共有 n!
种排列。
按大小顺序列出所有排列情况,并一一标记,当 n = 3
时, 所有排列如下:
"123"
"132"
"213"
"231"
"312"
"321"
给定 n
和 k
,返回第 k
个排列。
思想: 下一个排列的升级版。在下一个排列中,只用找到当前排列的下一个更大的排列。此题中,给定了 k值,输出第k个排列。所以在下一个排列的基础上,增加一个循环,让它找k-1次 下一个排列即可(k-1: 因为k=1,不应排列,按序输出即可)
61 给你一个链表的头节点 head
,旋转链表,将链表每个节点向右移动 k
个位置。
思想: 移动的特点在于:当移动的位置数等于链表长度时,链表就复原。
所以 分情况,若 链表长度小于向右移动的位置数,只用移动 k对链表长度的取余即可
若 链表长度大于向右移动的位置数, 找到移动前后的分界点即可。
66 . 加一 . 给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。你可以假设除了整数 0 之外,这个整数不会以零开头。
思想:
69. x 的平方根 :给你一个非负整数 x
,计算并返回 x
的 算术平方根 。由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5)
或者 x ** 0.5
。
思想: 二分查找: 从0-x之间确定一个数mid,若mid的平方<=x,则更新mid值,一直找到最后
数学思想: 求x的平方根,不能直接求,可以利用数学公式,转换形式,再求。
71 . 给你一个字符串 path
,表示指向某一文件或目录的 Unix 风格 绝对路径 (以 '/'
开头),请你将其转化为更加简洁的规范路径。在 Unix 风格的文件系统中,一个点(.
)表示当前目录本身;此外,两个点 (..
) 表示将目录切换到上一级(指向父目录);两者都可以是复杂相对路径的组成部分。任意多个连续的斜杠(即,'//'
)都被视为单个斜杠 '/'
。 对于此问题,任何其他格式的点(例如,'...'
)均被视为文件/目录名称。
请注意,返回的 规范路径 必须遵循下述格式:
- 始终以斜杠
'/'
开头。 - 两个目录名之间必须只有一个斜杠
'/'
。 - 最后一个目录名(如果存在)不能 以
'/'
结尾。 - 此外,路径仅包含从根目录到目标文件或目录的路径上的目录(即,不含
'.'
或'..'
)。
返回简化后得到的 规范路径 。
思想: 简化路径,观察可得路径是由'/' 分开个目录,由此 先按照 '/' 划分,在按照规则:若是空格和‘.’ 直接跳过;若是‘..’,则返回栈顶元素;若 是其他,直接append进栈
最后栈里所剩的 就是简化后的规范路径 ,使用 ‘/’.join()连接起来
73. 矩阵置零
给定一个 m x n
的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。
思想 : 搞一个列表,记录0所在位置,第二遍遍历matrix时,用0替换所在行列值
86. 分隔链表
给你一个链表的头节点 head
和一个特定值 x
,请你对链表进行分隔,使得所有 小于 x
的节点都出现在 大于或等于 x
的节点之前。
你应当 保留 两个分区中每个节点的初始相对位置
思想: 将值大于等于x的节点取出,构成新链表,并从原链表中删除x节点。最后将新链表接在原链表后面即可
88 . 合并两个有序数组
给你两个按 非递减顺序 排列的整数数组 nums1
和 nums2
,另有两个整数 m
和 n
,分别表示 nums1
和 nums2
中的元素数目。
请你 合并 nums2
到 nums1
中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1
中。为了应对这种情况,nums1
的初始长度为 m + n
,其中前 m
个元素表示应合并的元素,后 n
个元素为 0
,应忽略。nums2
的长度为 n
思想: 先将nums2 填到nums1中,在非递减排序
89 格雷编码n 位格雷码序列 是一个由 2n
个整数组成的序列,其中:
- 每个整数都在范围
[0, 2n - 1]
内(含0
和2n - 1
) - 第一个整数是
0
- 一个整数在序列中出现 不超过一次
- 每对 相邻 整数的二进制表示 恰好一位不同 ,且
- 第一个 和 最后一个 整数的二进制表示 恰好一位不同
给你一个整数 n
,返回任一有效的 n 位格雷码序列
思想: 格雷编码:n=3的结果是依据n=2的结果的,在n=2的结果后加上n=2结果的反序,并将后部分值的2进制前加上1,得到n=3的结果。