LeetCode
1、两数之和:给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。
2、两数相加:给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个节点只存储单个数字。将两数相加返回一个新的链表。
3、无重复字符的最长子串:给定一个字符串,找出不含有重复字符的最长子串的长度。
4、两个排序数组的中位数
5、最长回文子串:遍历字符串,从每个字符开始,往左右遍历看左右是否相等,相等继续往外扩散
6、Z字形变换
7、反转整数:除以10取余,取商注意负数、及溢出情况
8、回文数:判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数:注意负数;1、先转字符串再判断;2、反转一半数字
11、盛最多水的容器:给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
双指针法,一个指向开始,一个指向结尾,往中间移动
14、最长公共前缀:编写一个函数来查找字符串数组中的最长公共前缀。先遍历字符串数组,找出最短的字符串,遍历最短的字符串,和其他字符串一一比较;
15、三数之和:给定一个包含 n 个整数的数组 nums
,判断 nums
中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
先排序,遍历数组,以当前数为目标值,从当前数的后一个数开始,到最后一个之间查找两个数与目标值相加=0的数,如果大于0,则右边的下标左移,如果小于0,则左边的下标右移,直到右边的下标大于等于左边的下标,结束当前的查找,其实相当于第一题。
16、最接近的三数之和:给定一个包括 n 个整数的数组 nums
和 一个目标值 target
。找出 nums
中的三个整数,使得它们的和与 target
最接近。返回这三个数的和。假定每组输入只存在唯一答案。
同上题, 先排序,遍历数组,以当前数为目标值,从当前数的后一个数开始,到最后一个之间查找两个数与目标值相加接近target
的数,如果大于target
,则右边的下标左移,如果小于target
,则左边的下标右移,直到右边的下标大于等于左边的下标,结束当前的查找
18、四数之和四数之和:给定一个包含 n 个整数的数组 nums
和一个目标值 target
,判断 nums
中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target
相等?找出所有满足条件且不重复的四元组。
同上题,先排序,遍历数组,两个for循环
19、删除链表的倒数第N个节点:2个指针,一个先走N步后,另一个指针从头结点开始,当第一个指针走到最后,另一个节点走到倒数第N个
20、有效的括号:给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串,判断字符串是否有效。用LinkedList或者数组实现栈
21、合并两个有序链表:将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
23、合并K个排序链表:合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。递归:分一半,然后合并2个链表
24、两两交换链表中的节点:给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。注意头节点,使用两个指针指向待交换节点,注意判断最后两个尾节点是否为null
25、k个一组翻转链表:
给出一个链表,每 k 个节点一组进行翻转,并返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么将最后剩余节点保持原有顺序。
26、删除排序数组中的重复项
给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
count用于统计个数,作为结待排下标设置结果,cur设置当前值,用于比较下一个值是否相等,不相等则设置结果
27、移除元素
给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
同上;
28、实现strStr()
给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。
int i=0,j=0; while(i<len_s&&j<len_t){ if(haystack.charAt(i)==needle.charAt(j)){ i++; j++; }else { if((len_s-i-1)<len_t-j) return -1; i=i-j+1; j=0; } } return i-j;
30、与所有单词相关联的字串
给定一个字符串 s 和一些长度相同的单词 words。在 s 中找出可以恰好串联 words 中所有单词的子串的起始位置。
注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。
public class Solution { public List<Integer> findSubstring(String s, String[] words) { List<Integer> list = new ArrayList<Integer>(); int len=words.length; int len_s=s.length(); int len_word=words[0].length(); Map<String, Integer> map=new HashMap<String, Integer>(); for (int i = 0; i < len; i++) { if(map.containsKey(words[i])){ map.put(words[i], map.get(words[i])+1); }else { map.put(words[i], 1); } } String string=null; for(int i=0;i<=len_s-len*len_word;i++){ int count=0; int begin=i; string=s.substring(begin, begin+len_word); while(map.containsKey(string)&&map.get(string)>0){ map.put(string, map.get(string)-1); count++; begin+=len_word; if(begin+len_word>len_s){ break; } string=s.substring(begin, begin+len_word); } if(count==len){ list.add(i); } if(count>0){ map.clear(); for (int j = 0; j < len; j++) { if(map.containsKey(words[j])){ map.put(words[j], map.get(words[j])+1); }else { map.put(words[j], 1); } } } } return list; } }
31、下一个排列
实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须原地修改,只允许使用额外常数空间。
以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
1,2,3
→ 1,3,2
3,2,1
→ 1,2,3
1,1,5
→ 1,5,1
public class Solution { public void nextPermutation(int[] nums) { int i = nums.length - 2;
//从右向左找第一个正序 while (i >= 0 && nums[i + 1] <= nums[i]) { i--; }
//从右向左找第一个比nums[i]大的数 if (i >= 0) { int j = nums.length - 1; while (j >= 0 && nums[j] <= nums[i]) { j--; } swap(nums, i, j); }
//i后面的数反转 reverse(nums, i + 1); } private void reverse(int[] nums, int start) { int i = start, j = nums.length - 1; while (i < j) { swap(nums, i, j); i++; j--; } } private void swap(int[] nums, int i, int j) { int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; } }
32、最长有效括号
给定一个只包含 '('
和 ')'
的字符串,找出最长的包含有效括号的子串的长度。
public class Solution { public int longestValidParentheses(String s) { int len=0; int [] aa=new int[s.length()]; for(int i=0;i<s.length();i++){ if(s.charAt(i)=='(') aa[i]=0; else { int pre=i-1; while(pre>=0&&aa[pre]>0){ pre-=aa[pre]; } if(pre>=0&&s.charAt(pre)=='('){ aa[i]=i-pre+1; if(pre>0){ aa[i]+=aa[pre-1]; } } } len=Math.max(len, aa[i]); } return len; } }
34、在排序数组中查找元素的第一个和最后一个位置
给定一个按照升序排列的整数数组 nums
,和一个目标值 target
。找出给定目标值在数组中的开始位置和结束位置。
你的算法时间复杂度必须是 O(log n) 级别。
如果数组中不存在目标值,返回 [-1, -1]
。
35、搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素。
36、有效的数独
判断一个 9x9 的数独是否有效。只需要根据以下规则,验证已经填入的数字是否有效即可。
- 数字
1-9
在每一行只能出现一次。 - 数字
1-9
在每一列只能出现一次。 - 数字
1-9
在每一个以粗实线分隔的3x3
宫内只能出现一次。
三个List<Set<Character>> r=new ArrayList<Set<Character>>();
38、
报数序列是指一个整照其中的整数的顺序进数序列,按行报数,得到下一个数。其前五项如下:
1. 1 2. 11 3. 21 4. 1211 5. 111221
1
被读作 "one 1"
("一个一"
) , 即 11
。
11
被读作 "two 1s"
("两个一"
), 即 21
。
21
被读作 "one 2"
, "one 1"
("一个二"
, "一个一"
) , 即 1211
。
给定一个正整数 n(1 ≤ n ≤ 30),输出报数序列的第 n 项。
注意:整数顺序将表示为一个字符串。
public class Solution { public String countAndSay(int n) { if (n == 1) return "1"; String str = countAndSay(n - 1)+"*"; char[] c = str.toCharArray(); int count = 1; String s = ""; for (int i = 0; i < c.length - 1; i++) { if (c[i] == c[i + 1]) { count++; } else { s += count + "" + c[i]; count = 1; } } return s; } }
39. 组合总和
给定一个无重复元素的数组 candidates
和一个目标数 target
,找出 candidates
中所有可以使数字和为 target
的组合。
candidates
中的数字可以无限制重复被选取。
public class Solution { List<List<Integer>> lists = new ArrayList<List<Integer>>(); public List<List<Integer>> combinationSum(int[] candidates, int target) { Arrays.sort(candidates); backTrackeing(new ArrayList<Integer>(),candidates,0, target); return lists; } private void backTrackeing(ArrayList<Integer> cur, int[] candidates, int from, int target) { if(target==0){ List<Integer> list=new ArrayList<Integer>(cur); lists.add(list); }else { for(int i=from;i<candidates.length&&candidates[i]<=target;i++){ cur.add(candidates[i]); backTrackeing(cur, candidates, i, target-candidates[i]); cur.remove(new Integer(candidates[i])); } } } }
40. 组合总和 II
给定一个数组 candidates
和一个目标数 target
,找出 candidates
中所有可以使数字和为 target
的组合。
candidates
中的每个数字在每个组合中只能使用一次。
说明:
- 所有数字(包括目标数)都是正整数。
- 解集不能包含重复的组合。
41. 缺失的第一个正数
给定一个未排序的整数数组,找出其中没有出现的最小的正整数。
public class Solution { public int firstMissingPositive(int[] nums) { for (int i = 0; i < nums.length; i++) { while (nums[i] > 0 && nums[i] <= nums.length && nums[nums[i] - 1] != nums[i]) { int tmp = nums[nums[i] - 1]; nums[nums[i] - 1] = nums[i]; nums[i] = tmp; } } for (int i = 0; i < nums.length; i++) { if (nums[i] != i + 1) return i + 1; } return nums.length+1; } }
42、接雨水
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 感谢 Marcos 贡献此图。
示例:
输入: [0,1,0,2,1,0,1,3,2,1,2,1] 输出: 6
public class Solution { public int trap(int[] height) { int rainV=0; int l=0,r=height.length-1; while(l<r&&height[l]<=height[l+1]) l++; while(l<r&&height[r]<=height[r-1]) r--; while(l<r){ int left=height[l]; int right=height[r]; if(left<=right){ while(l<r&&left>=height[++l]){ rainV+=left-height[l]; } }else { while(l<r&&right>=height[--r]){ rainV+=right-height[r]; } } } return rainV; } }
从两边开始,左边找后边比前面高度小的,右边找前面比后面高的,左边下标小于右边
45. 跳跃游戏 II
给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。
public class Solution { public int jump(int[] A) { if(A.length<=1){ return 0; } int i=0,j=0; int count=0; while(i<A.length){
//注意方法出口 if(i+A[i]>=A.length-1){ count++; return count; }
//寻找当前数后面几位中最大的值 int temp=Integer.MIN_VALUE; for(int k=i+1;k<=i+A[i];k++){ if(temp<k+A[k]){ temp=k+A[k]; j=k; } }
//从最大值后再继续查找 i=j; count++; } return 0; } }
55、跳跃游戏
给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个位置。
public class Solution { public boolean canJump(int[] nums) { int reach=0; int i=0; for(;i<nums.length&&i<=reach;i++){ reach=Math.max(reach,i+nums[i]); } return (i==nums.length); } }
46. 全排列
给定一个没有重复数字的序列,返回其所有可能的全排列。
斐波那契计算所有排序的情况数,
List<List<Integer>> lists=new ArrayList<List<Integer>>();记录结果集
从右往左找到第一个正序,再从右往左找到第一个比它大的数,交换两个数,再将后面的数反转
47、全排列 II
给定一个可包含重复数字的序列,返回所有不重复的全排列。
public class Solution { public void rotate(int[][] matrix) { int n=matrix.length;//若n=4 int count=(n-1)/2;//矩阵有几圈=count+1 for(int i=0;i<=count;i++){//i=0,1 for(int j=i;j<n-i-1;j++){//当i=0时,j=0,1,2 当i=1时,j=1 int tmp=matrix[i][j]; matrix[i][j]=matrix[n-j-1][i]; matrix[n-j-1][i]=matrix[n-i-1][n-j-1]; matrix[n-i-1][n-j-1]=matrix[j][n-i-1]; matrix[j][n-i-1]=tmp; } } } }
49、字母异位词分组
给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
public class Solution { public List<List<String>> groupAnagrams(String[] strs) { List<List<String>> lists=new ArrayList<List<String>>(); Map<String, List<String>> map=new HashMap<String, List<String>>(); for(int i=0;i<strs.length;i++){ char []c=strs[i].toCharArray(); Arrays.sort(c); String str=String.valueOf(c); if(!map.containsKey(str)){ List<String> list=new ArrayList<String>(); map.put(str, list); } map.get(str).add(strs[i]); } for(String key:map.keySet()){ Collections.sort(map.get(key)); lists.add(map.get(key)); } return lists; } }
53. 最大子序和
给定一个整数数组 nums
,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
public class Solution { public int maxSubArray(int[] nums) { int sum=Integer.MIN_VALUE; int maxNum=Integer.MIN_VALUE;; for(int i=0;i<nums.length;i++){ if(sum>0){ sum+=nums[i]; }else { sum=nums[i]; } if(sum>maxNum) maxNum=sum; } return maxNum; } }
54. 螺旋矩阵
给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。
int top=0,bottom=m-1,left=0,right=n-1;
int loop=m<n?m:n;
loop=(loop+1)/2;
60. 第k个排列
给出集合 [1,2,3,…,n]
,其所有元素共有 n! 种排列。
按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:
"123"
"132"
"213"
"231"
"312"
"321"
给定 n 和 k,返回第 k 个排列。
说明:
- 给定 n 的范围是 [1, 9]。
- 给定 k 的范围是[1, n!]。
public class Solution { public String getPermutation(int n, int k) { List<Integer> list=new ArrayList<Integer>(); int s=1; String str=""; for(int i=1;i<=n;i++){ list.add(i); s*=i; } int a,b; k--; while(list.size()!=1){ if(k==0) { for (Integer x : list) { str+=x; } return str; } a=k/Factorial(n-1); k=(k-Factorial(n-1)*a)%Factorial(n-1); str+=list.get(a); list.remove(a); n--; } str+=list.get(0); return str; } public int Factorial(int n){ if(n==1||n==0) return 1; else { return Factorial(n-1)*n; } } }
61、旋转链表
给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数。
62. 不同路径
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
问总共有多少条不同的路径?
C7,2
63、不同路径2
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
使用二维数组,标记若当前值为1则,标记0;
遍历二维数组,若原数组当前值为1,则记为0,其余均为其上和其左数值之和;
返回最后一个数值;
64. 最小路径和
给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
public class Solution { public int minPathSum(int[][] grid) { int m=grid.length; int n=grid[0].length; int []ans=new int [n]; ans[0]=grid[0][0]; for(int i=1;i<n;i++){ ans[i]=ans[i-1]+grid[0][i]; } for(int i=1;i<m;i++){ ans[0]+=grid[i][0]; for(int j=1;j<n;j++){ ans[j]=Math.min(ans[j-1], ans[j])+grid[i][j]; } } return ans[n-1]; } }
66. 加一
给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。
最高位数字存放在数组的首位, 数组中每个元素只存储一个数字。
你可以假设除了整数 0 之外,这个整数不会以零开头。
public class Solution { public int minPathSum(int[][] grid) { int m=grid.length; int n=grid[0].length; int []ans=new int [n]; ans[0]=grid[0][0]; for(int i=1;i<n;i++){ ans[i]=ans[i-1]+grid[0][i]; } for(int i=1;i<m;i++){ ans[0]+=grid[i][0]; for(int j=1;j<n;j++){ ans[j]=Math.min(ans[j-1], ans[j])+grid[i][j]; } } return ans[n-1]; } }
67. 二进制求和
给定两个二进制字符串,返回他们的和(用二进制表示)。
输入为非空字符串且只包含数字 1
和 0
。
70. 爬楼梯
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
public class Solution { public int climbStairs(int n) { if (n == 0 || n == 1 || n == 2) return n; int[] aa = new int[n]; aa[0] = 1; aa[1] = 2; for (int i = 2; i < n; i++) { aa[i] = aa[i - 1] + aa[i - 2]; } return aa[n - 1]; } }
73. 矩阵置零
给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0。请使用原地算法。
先遍历第一行和第一列,是否存在含0的数据,是则标记;
再遍历数组,用第一行第一列来标记这一行一列是否存在含0的数,是的话置0;
遍历第一行和第一列,将为0的对应的列和行,置为0;
再检验原第一行和第一列是否存在含0数据,是的话,也置为0
75. 颜色分类
给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
public class Solution { public void sortColors(int[] nums) { int i = -1, j = -1, k = -1; for (int m = 0; m < nums.length; m++) { if (nums[m] == 0) { nums[++k] = 2; nums[++j] = 1; nums[++i] = 0; } else if (nums[m] == 1) { nums[++k] = 2; nums[++j] = 1; } else { nums[++k] = 2; } } } }
78、子集
public class Solution { List<List<Integer>> lists = new ArrayList<List<Integer>>(); public List<List<Integer>> subsets(int[] nums) { Arrays.sort(nums); for (int i = 0; i <=nums.length; i++) { backTracking(new ArrayList<Integer>(), nums, 0, i); } return lists; } private void backTracking(ArrayList<Integer> cur, int[] nums, int from, int target) { // TODO Auto-generated method stub if (cur.size() == target) { List<Integer> list = new ArrayList<Integer>(cur); lists.add(list); } else { for (int i = from; i < nums.length; i++) { cur.add(nums[i]); backTracking(cur, nums, i + 1, target); cur.remove(new Integer(nums[i])); } } } }
英文:https://leetcode.com/problemset/all/
中文:https://leetcode-cn.com/