LeetCode

1、两数之和:给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。

2、两数相加:给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个节点只存储单个数字。将两数相加返回一个新的链表。

3、无重复字符的最长子串:给定一个字符串,找出不含有重复字符的最长子串的长度。

4、两个排序数组的中位数

5、最长回文子串:遍历字符串,从每个字符开始,往左右遍历看左右是否相等,相等继续往外扩散

6、Z字形变换

7、反转整数:除以10取余,取商注意负数、及溢出情况

8、回文数:判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数:注意负数;1、先转字符串再判断;2、反转一半数字

11、盛最多水的容器:给定 n 个非负整数 a1a2,...,an,每个数代表坐标中的一个点 (iai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (iai) 和 (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个排序链表:合并 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。递归:分一半,然后合并2个链表

24、两两交换链表中的节点:给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。注意头节点,使用两个指针指向待交换节点,注意判断最后两个尾节点是否为null

25、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、与所有单词相关联的字串

给定一个字符串 和一些长度相同的单词 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,31,3,2
3,2,11,2,3
1,1,51,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. 数字 1-9 在每一行只能出现一次。
  2. 数字 1-9 在每一列只能出现一次。
  3. 数字 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 中的每个数字在每个组合中只能使用一次。

说明:

  • 所有数字(包括目标数)都是正整数。
  • 解集不能包含重复的组合。
同上,递归从i+1开始

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 时, 所有排列如下:

  1. "123"
  2. "132"
  3. "213"
  4. "231"
  5. "312"
  6. "321"

给定 n 和 k,返回第 k 个排列。

说明:

  • 给定 n 的范围是 [1, 9]。
  • 给定 的范围是[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、旋转链表

给定一个链表,旋转链表,将链表每个节点向右移动 个位置,其中 是非负数。

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/

posted @ 2018-09-29 19:21  提拉米苏007  阅读(381)  评论(0编辑  收藏  举报