记录leetcode的一些解法

所有算法都是自己写的,有时间会再回来优化,先AC练手,准备按顺序刷题了,不知道能刷多少,希望能刷个200多题把。先立个flag!

1. Two Sum

Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] result = new int[2];
        int size = nums.length;
        for(int i =0; i<size ;i++){
            for(int j = i+1 ;j<size ;j++){
                int sum = nums[i]+nums[j];
                if(sum == target){
                    result[0]=i;
                    result[1]=j;
                    return result;
                }
            }
        }
        return null;
    }
}

2. Add Two Numbers

You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.

You may assume the two numbers do not contain any leading zero, except the number 0 itself.

Example:

Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
Explanation: 342 + 465 = 807.

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode head = new ListNode(0);
        ListNode p = l1;
        ListNode q = l2;
        ListNode now = head;
        
        while(!(p ==null && q == null)){
            if(p != null){
                now.val += p.val;
                 p = p.next;
            }
            
            if(q != null){
                now.val += q.val;
                q = q.next;
            }
            
            
            ListNode next = new ListNode(0);                        
            if(now.val >= 10){                
                now.val -= 10;
                next.val = 1;
                
            }
            now.next=next;
            
            if(p==null && q==null && next.val == 0){
                 now.next = null;
            }else{               
                now = now.next;
            }
                        
        }
             
        return head;
    }
}

3. 无重复的最长子串

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。

示例 2:

输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。

示例 3:

输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。

class Solution {
    public int lengthOfLongestSubstring(String s) {
        int length = s.length();
        if(length ==0){
            return 0;
        }
        int begin = 0;
        int end = 1;
        boolean flag = true;
        while(end <= length){
            flag = true;
            for(int i = begin ;i < end; i++){              
                for(int j = i + 1; j <= end  ;j++){
                    if(j == length ){
                        begin++;
                        end++;
                        flag = false;
                        break;
                    }
                    if(s.charAt(i) == s.charAt(j)){
                        begin++;
                        end++;
                        flag = false;
                        break;
                    }
                }
                if(flag == false){
                    break;
                }
            }
            if(flag == true){
               end = end + 1;
            } 
        }
               
    return end-begin;
       
    }
}

4.寻找两个有序数组的中位数

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。

请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。

你可以假设 nums1 和 nums2 不会同时为空。

示例 1:

nums1 = [1, 3]
nums2 = [2]

则中位数是 2.0

示例 2:

nums1 = [1, 2]
nums2 = [3, 4]

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int size1 = nums1.length;
        int size2 = nums2.length;

        if(size1 == 0 || size2 == 0){
            int[] newnum = size1 > size2 ? nums1 : nums2;
            int size = newnum.length;
            if(size % 2 == 0){
                return 1.0 * ( newnum[size/2] + newnum[size/2 -1] ) / 2;
            }else{
                return 1.0 * ( newnum[size/2] );
            }
        }

        int totalLength = size1 + size2;
        int harfsize = totalLength / 2;

        int position1 = 0;
        int position2 = 0;

        boolean single = true;
        if(totalLength % 2 == 0){
            single = false;
        }

        if(single){

            while(harfsize > 0){
                if(nums1[position1] >= nums2[position2] && position2 < size2-1){
                    position2++;                   
                }else if(nums1[position1] <= nums2[position2] && position1 < size1-1){
                    position1++;                   
                }else{
                    if(position1 < size1-1){
                        return 1.0 * nums1[position1 + harfsize -1];
                    }else if(position2 < size2-1){
                        return 1.0 * nums2[position2 + harfsize -1];
                    }
                }
                harfsize--;
            }
            int finalresult = nums1[position1] < nums2[position2] ? nums1[position1]:nums2[position2];
            return 1.0 * finalresult;

        }else{
            while(harfsize-1 > 0){
                if(nums1[position1] >= nums2[position2] && position2 < size2-1){
                    position2++;                   
                }else if(nums1[position1] <= nums2[position2] && position1 < size1-1){
                    position1++;                   
                }else{
                    if(position1 < size1-1){
                        return 1.0 * (nums1[position1 + harfsize -1] + nums1[position1 + harfsize -2]) / 2 ;
                    }else if(position2 < size2-1){
                        return 1.0 * (nums2[position2 + harfsize -1] + nums2[position2 + harfsize -2]) / 2;
                    }
                }
                harfsize--;
            }           
            int smallone = nums1[position1] < nums2[position2] ? 1 : 2;
            int smallnum = nums1[position1] < nums2[position2] ? nums1[position1] : nums2[position2];
            int bignum = 0;
            if(position1 < size1-1 && smallone == 1){
                bignum = nums1[position1 + 1] < nums2[position2] ? nums1[position1 + 1] : nums2[position2];
            }else if(position2 < size2-1 && smallone == 2){
                bignum = nums1[position1] < nums2[position2 + 1] ? nums1[position1] : nums2[position2 + 1];
            }else{
                return 1.0 * (nums1[position1] + nums2[position2]) / 2 ;
            }
            return 1.0 * (smallnum + bignum) / 2 ;
            
        }
        

    }
}

5.最长回文子串

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

示例 1:

输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。

示例 2:

输入: “cbbd”
输出: “bb”

class Solution {
    public String longestPalindrome(String s) {
        String max = "";
        int maxLength = 0;
        int size = s.length();
        for(int nowPos = 0 ; nowPos < size ; nowPos++){
            int finalPos = nowPos,beforePos = nowPos;
            while( finalPos + 1 < size){
                if(s.charAt(nowPos) == s.charAt(finalPos+1)){
                    finalPos ++ ;
                }else{
                    break;
                }
            }
            while( finalPos + 1 < size && beforePos -1 >= 0 ){
                if(s.charAt(beforePos -1) == s.charAt(finalPos+1)){
                    finalPos ++ ;
                    beforePos --;
                }else{
                    break;
                }
            }
            String nowStr = s.substring(beforePos,finalPos+1);
            int nowNum = nowStr.length();
            if(nowNum > maxLength){
                maxLength = nowNum;
                max = new String(nowStr);
            }
        }
        return max;
    }
}

6. Z 字形变换

将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。

比如输入字符串为 “LEETCODEISHIRING” 行数为 3 时,排列如下:

L   C   I   R
E T O E S I I G
E   D   H   N

之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“LCIRETOESIIGEDHN”。

请你实现这个将字符串进行指定行数变换的函数:

string convert(string s, int numRows);

示例 1:

输入: s = “LEETCODEISHIRING”, numRows = 3
输出: “LCIRETOESIIGEDHN”

示例 2:

输入: s = “LEETCODEISHIRING”, numRows = 4
输出: “LDREOEIIECIHNTSG”
解释:

L     D     R
E   O E   I I
E C   I H   N
T     S     G
class Solution {
    public String convert(String s, int numRows) {
        StringBuilder str = new StringBuilder();
        //长度
        int size = s.length();
        if(numRows == 1){
            return s;
        }

        for(int row = 0; row < numRows; row++){
            if(row < size){
                str.append(s.charAt(row));
            }else{
                break;
            }

            int add = 2 * (numRows-1-row);
            int position = row;
            while((position + add) < size){
                position = position + add;
                if(add != 0){
                    str.append(s.charAt(position));
                }
                add = (numRows-1)*2 - add;
            }
        }
        return str.toString();
        
    }
}

7. 整数反转

给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。

示例 1:

输入: 123
输出: 321

 示例 2:

输入: -123
输出: -321

示例 3:

输入: 120
输出: 21

注意:

假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231, 231 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。

class Solution {
    public int reverse(int x) {
        if(x == 0){
            return 0;
        }
        String s=String.valueOf(x);         
        int i = 0;
        StringBuilder str = new StringBuilder();
        if(s.charAt(i) == '-'){
            i++;
            str.append('-');
        }
        boolean flag = true;
        for(int j = s.length()-1 ; j >= i ; j--){
            if(flag == true){
                if(s.charAt(j) != '0'){
                    str.append(s.charAt(j));
                    flag = false;
                }
            }else{
                str.append(s.charAt(j));
            }
                  
        }
        Long num = Long.parseLong(str.toString());
        Long l1 = Long.parseLong("2147483647");
        Long l2 = Long.parseLong("-2147483647");
        if(num.longValue() < l1.longValue() && num.longValue() > l2.longValue()){
            return Integer.parseInt(str.toString());
        }
        return 0;
        
    }
}

8. 字符串转换整数 (atoi)

请你来实现一个 atoi 函数,使其能将字符串转换成整数。

首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。

当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。

该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。

注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。

在任何情况下,若函数不能进行有效的转换时,请返回 0。

说明:

假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,请返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。

示例 1:

输入: “42”
输出: 42

示例 2:

输入: " -42"
输出: -42
解释: 第一个非空白字符为 ‘-’, 它是一个负号。
我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。

示例 3:

输入: “4193 with words”
输出: 4193
解释: 转换截止于数字 ‘3’ ,因为它的下一个字符不为数字。

示例 4:

输入: “words and 987”
输出: 0
解释: 第一个非空字符是 ‘w’, 但它不是数字或正、负号。
因此无法执行有效的转换。

示例 5:

输入: “-91283472332”
输出: -2147483648
解释: 数字 “-91283472332” 超过 32 位有符号整数范围。
因此返回 INT_MIN (−231) 。

class Solution {
    public int myAtoi(String str) {
        StringBuilder s = new StringBuilder();
        boolean flag0 = true;
        boolean flag1 = true;
        boolean flag2 = true;
        for(int i = 0; i < str.length(); i++){
            char c = str.charAt(i);
            //‘ ’空仅有开头可以省略
            if(c == ' ' && s.length() == 0 && flag2 == true && flag0 ==true){
                continue;
            }
            if(c == '0' && (s.length() == 0 || (flag1 == false && s.length() == 1))){
                flag0 = false;
                continue;
            }
            if(c == '-' && s.length() == 0 && flag1==true && flag2 == true && flag0 ==true){
                s.append(c);
                flag1 = false;
                continue;
            } 
            if(c == '+' && s.length() == 0 && flag2==true && flag1==true && flag0 ==true){
                flag2 = false;
                continue;
            }            
            if(Character.isDigit(c)){
                s.append(c);
            }else{
                if(s.length() == 0){
                    return 0;
                }else{
                    break;
                }
            }

            if(!Character.isDigit(c) && s.length() == 0){
                return 0;
            }
        }



        if(s.length() == 0){
            return 0;
        }
        if(s.length() == 1 && flag1 == false){
            return 0;
        }
        if(s.length() >11 ){
            if(flag1 == false){
                return -2147483648;
            }else{
                return 2147483647;
            }

        }
        Long num = Long.parseLong(s.toString());
        Long l1 = Long.parseLong("2147483647");
        Long l2 = Long.parseLong("-2147483647");
        if(num.longValue() > l1.longValue()){
            return 2147483647;
        }else if(num.longValue() < l2.longValue()){
            return -2147483648;
        }else{
            return Integer.parseInt(s.toString());
        }
        
    }
}

9. 回文数

判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。

示例 1:

输入: 121
输出: true

示例 2:

输入: -121
输出: false
解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。

示例 3:

输入: 10
输出: false
解释: 从右向左读, 为 01 。因此它不是一个回文数。

class Solution {
    public boolean isPalindrome(int x) {
        String str = String.valueOf(x);
        boolean flag = true;
        int num = str.length();
        for(int i = 0, j = num-1; i <= j; i++,j--){
            if(str.charAt(i) != str.charAt(j)){
                flag = false;
                break;
            }
        }
        return flag;
        
    }
}

10. 正则表达式匹配

给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 ‘.’ 和 ‘*’ 的正则表达式匹配。

‘.’ 匹配任意单个字符
‘*’ 匹配零个或多个前面的那一个元素

所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。

说明:

s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 *。

示例 1:

输入:
s = “aa”
p = “a”
输出: false
解释: “a” 无法匹配 “aa” 整个字符串。

示例 2:

输入:
s = “aa”
p = “a*”
输出: true
解释: 因为 ‘*’ 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 ‘a’。因此,字符串 “aa” 可被视为 ‘a’ 重复了一次。

示例 3:

输入:
s = “ab”
p = “."
输出: true
解释: ".
” 表示可匹配零个或多个(’*’)任意字符(’.’)。

示例 4:

输入:
s = “aab”
p = “cab”
输出: true
解释: 因为 ‘*’ 表示零个或多个,这里 ‘c’ 为 0 个, ‘a’ 被重复一次。因此可以匹配字符串 “aab”。

示例 5:

输入:
s = “mississippi”
p = “misisp*.”
输出: false

class Solution {
    public boolean isMatch(String s, String p) {
        boolean flag = false;
        int sizei = s.length();
        int sizej = p.length();
        if(sizei == 0 && sizej == 0){
            return true;
        }
        if( sizei != 0 && sizej == 0){
            return false;    
        }
        if(sizei == 0 && sizej != 0 ){
            while( sizej % 2 == 0 && p.charAt(sizej - 1) == '*'){
                sizej = sizej - 2;
                if(sizej == 0){
                    return true;
                }
            }           
            return false;
        }
        int posi = sizei - 1;
        int posj = sizej - 1;
        char ci = s.charAt(posi);
        char cj = p.charAt(posj);
        if(ci == cj || cj == '.'){
            String s1 = s.substring(0,posi);
            String s2 = p.substring(0,posj);
            return isMatch(s1,s2);
        }else if(cj == '*'){
            //*前无匹配字符返回错误
            if(posj==0){
                return false;
            }
            //连续两个** 返回错误
            posj = posj - 1;
            char before = p.charAt(posj);
            if(before == '*'){
                return false;
            }
            char compare = ci;
            flag = flag || isMatch(s,p.substring(0,posj));
            while( compare == before || before == '.'){  
                flag = flag || isMatch(s.substring(0,posi),p.substring(0,posj));
                posi--;  
                if(posi >= 0){
                    compare = s.charAt(posi);
                }else{
                    break;
                }
            }
        }else{
            return false;
        }

        return flag;       
    }
}

11. 盛最多水的容器

给定 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

说明:你不能倾斜容器,且 n 的值至少为 2。

图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

示例:

输入: [1,8,6,2,5,4,8,3,7]
输出: 49

class Solution {
    public int maxArea(int[] height) {
        int length = height.length;
        int max = 0;
        int size =0;
        for(int i=0;i<length;i++){
            for(int j=i+1;j<length;j++){
                int small = height[i]<height[j]?height[i]:height[j];
                size = small * (j-i);
                if(size>max){
                    max = size;
                }
            }
        }
        return max;
    }
}

12. 整数转罗马数字

罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000

例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。 
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。

给定一个整数,将其转为罗马数字。输入确保在 1 到 3999 的范围内。

示例 1:

输入: 3
输出: “III”

示例 2:

输入: 4
输出: “IV”

示例 3:

输入: 9
输出: “IX”

示例 4:

输入: 58
输出: “LVIII”
解释: L = 50, V = 5, III = 3.

示例 5:

输入: 1994
输出: “MCMXCIV”
解释: M = 1000, CM = 900, XC = 90, IV = 4.

class Solution {
    public String intToRoman(int num) {
        StringBuilder str = new StringBuilder();
        int numM = num / 1000;
        int restM = num % 1000;
        while(numM > 0){
            str.append('M');
            numM --;
        }
        if(restM >= 900){
            str.append("CM");
            restM -= 900;
        }

        int numD = restM / 500;
        int restD = restM % 500;

        while(numD > 0){
            str.append('D');
            numD --;
        }
        if(restD >= 400){
            str.append("CD");
            restD -= 400;
        }

        int numC = restD / 100;
        int restC = restD % 100;

        while(numC > 0){
            str.append('C');
            numC --;
        }
        if(restC >= 90){
            str.append("XC");
            restC -= 90;
        }

        int numL = restC / 50;
        int restL = restC % 50;

        while(numL > 0){
            str.append('L');
            numL --;
        }
        if(restL >= 40){
            str.append("XL");
            restL -= 40;
        }

        int numX = restL / 10;
        int restX = restL % 10;

        while(numX > 0){
            str.append('X');
            numX --;
        }
        if(restX >= 9){
            str.append("IX");
            restX -= 9;
        }

        int numV = restX / 5;
        int restV = restX % 5;

        while(numV > 0){
            str.append('V');
            numV --;
        }
        if(restV >= 4){
            str.append("IV");
            restV -= 4;
        }
        while(restV > 0){
            str.append('I');
            restV --;
        }
        return str.toString();
    }
}

13. 罗马数字转整数

罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000

例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。 
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。

给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。

示例 1:

输入: “III”
输出: 3

示例 2:

输入: “IV”
输出: 4

示例 3:

输入: “IX”
输出: 9

示例 4:

输入: “LVIII”
输出: 58
解释: L = 50, V= 5, III = 3.

示例 5:

输入: “MCMXCIV”
输出: 1994
解释: M = 1000, CM = 900, XC = 90, IV = 4.

class Solution {
    public int romanToInt(String s) {
        int sum = 0;
        int pos = 0;
        while(pos < s.length()){
            StringBuilder a = new StringBuilder();
            char b = s.charAt(pos);
            a.append(b);
            if(pos < s.length() - 1){
                char next = s.charAt(pos + 1);
                if((b=='C'&&(next == 'M' || next == 'D')) 
                || (b == 'X' && (next == 'C' || next == 'L') )
                || (b == 'I' && (next == 'X' || next == 'V') )){
                    a.append(next);
                    pos ++;
                }

            }
            String val = a.toString();
            
            switch(val){
                case "M": sum += 1000;break;
                case "D": sum += 500;break;
                case "C": sum += 100;break;
                case "L": sum += 50;break;
                case "X": sum += 10;break;
                case "V": sum += 5;break;
                case "I": sum += 1;break;
                case "IV": sum += 4;break;
                case "IX": sum += 9;break;
                case "XC": sum += 90;break;
                case "XL": sum += 40;break;
                case "CM": sum += 900;break;
                case "CD": sum += 400;break;
            }
            pos ++;
        }

        return sum;
    }
}

14. 最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。

如果不存在公共前缀,返回空字符串 “”。

示例 1:

输入: [“flower”,“flow”,“flight”]
输出: “fl”

示例 2:

输入: [“dog”,“racecar”,“car”]
输出: “”
解释: 输入不存在公共前缀。

说明:

所有输入只包含小写字母 a-z 。

class Solution {
    public String longestCommonPrefix(String[] strs) {
        int size = strs.length;
        if(size == 0){
            return "";
        }
        StringBuilder s = new StringBuilder();
        int sim = 0;
        boolean flag = true;
        while(flag){
            char compare;
            if(sim < strs[0].length()){
                compare = strs[0].charAt(sim);
            }else{
                break;
            }
            for(int i = 1; i < size; i++ ){
                if(sim < strs[i].length()){
                    if(strs[i].charAt(sim) != compare){
                        flag = false;
                        break;
                    }               
                }else{
                    flag = false;
                    break;
                }
            }
            if(flag){
                sim++;
                s.append(compare);
            }
        }
        
        return s.toString();
    }
}

15. 三数之和

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> result = new ArrayList();
        Map<Integer,Integer> numMap = new HashMap();
        TreeSet<Integer> treeSet = new TreeSet<>();
        for(int i = 0; i < nums.length; i++){
            if(numMap.get(nums[i]) == null){
                numMap.put(nums[i],1);
                treeSet.add(nums[i]);
            }else{
                int val = numMap.get(nums[i]);
                numMap.put(nums[i], 1 + val);
            }
        }
        Iterator<Integer> it =  treeSet.iterator();
        while(it.hasNext()) {
            Integer intI = it.next();
            if(numMap.get(intI) >= 2 ){
                if(intI == 0 && numMap.get(intI)< 3 ){
                    continue;
                }else if(numMap.get(-2 * intI) != null){
                    List<Integer> item = new ArrayList();
                    item.add(intI);
                    item.add(intI);
                    item.add(-2*intI);
                    result.add(item);
                }
            }
        }
        Object[] arr = treeSet.toArray();
        for(int i = 0; i < arr.length; i++){
            Integer n1 = (Integer)arr[i];
            for(int j = i+1; j < arr.length; j++){
                Integer n2 = (Integer)arr[j];
                if(numMap.get(-n1-n2) != null && -n1-n2 > n2){
                    List<Integer> item = new ArrayList();
                    item.add(n1);
                    item.add(n2);
                    item.add(-n1-n2);
                    result.add(item);
                }
            }
        }        
        return result;
    }
}

16. 最接近的三数之和

给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。

例如,给定数组 nums = [-1,2,1,-4], 和 target = 1.

与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2).

class Solution {
    public int threeSumClosest(int[] nums, int target) {
        int result = 0;
        if(nums.length < 3){
            return 0;
        }
        Arrays.sort(nums);
        int min = Integer.MAX_VALUE;
        for(int i = 0; i < nums.length; i++){
            int before = i + 1;
            int end = nums.length - 1;
            while(before < end){
                int totalNum = nums[i] + nums[before] + nums[end];
                int distance = totalNum > target ? totalNum - target : target - totalNum;
                if(distance == 0){
                    return target;
                }
                if(min > distance){
                    min = distance;
                    result = totalNum;
                }
                if(totalNum > target ){
                    end--;
                }else{
                    before ++;
                }
            }
            
        }
        return result;
    }
}

17. 电话号码的字母组合

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
在这里插入图片描述

示例:

输入:“23”
输出:[“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”].

说明:
尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。

class Solution {
    public List<String> letterCombinations(String digits) {
        List<String> result = new ArrayList();
        if(digits.length() == 0){
            return result;
        }
        String a = digits.substring(0,1);
        List<String> result2 = new ArrayList();
            switch(a){
            case"2": 
                result2.add("a");
                result2.add("b");
                result2.add("c");
                break;
            case"3": 
                result2.add("d");
                result2.add("e");
                result2.add("f");
                break;
            case"4": 
                result2.add("g");
                result2.add("h");
                result2.add("i");
                break;
            case"5": 
                result2.add("j");
                result2.add("k");
                result2.add("l");
                break;
            case"6": 
                result2.add("m");
                result2.add("n");
                result2.add("o");
                break;
            case"7": 
                result2.add("p");
                result2.add("q");
                result2.add("r");
                result2.add("s");
                break;
            case"8": 
                result2.add("t");
                result2.add("u");
                result2.add("v");
                break;
            case"9": 
                result2.add("w");
                result2.add("x");
                result2.add("y");
                result2.add("z");
                break;               
        }
        if(digits.length() == 1){
            return result2;
        }
        List<String> suffix = letterCombinations(digits.substring(1,digits.length()));
        for(int i = 0; i < result2.size(); i++){
            for(int j = 0; j < suffix.size() ; j++){
                result.add(result2.get(i) + suffix.get(j));
            }
        }
        return result;
    }
}

18. 4数之和

给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。

注意:

答案中不可以包含重复的四元组。

示例:

给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。

满足要求的四元组集合为:
[
[-1, 0, 0, 1],
[-2, -1, 1, 2],
[-2, 0, 0, 2]
]

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> result = new ArrayList();
        if(nums.length < 4){
            return result;
        }
        Arrays.sort(nums);
        for(int i = 0; i < nums.length; i++){
            while(i >= 1 && i < nums.length && nums[i] == nums[i-1]){
                i ++;
            }
            for(int j = i + 1; j < nums.length - 2; j++ ){
                while(j >= i + 2 && j < nums.length - 2 && nums[j] == nums[j-1]){
                    j ++;
                }
                if(nums[i] + nums[j] > target && target > 0){
                    break;
                }
                int beforePos = j + 1;
                int endPos = nums.length - 1;
                while(beforePos < endPos){
                    if(nums[i] + nums[j] + nums[beforePos] + nums[endPos] == target){
                        List<Integer> item = new ArrayList();
                        item.add(nums[i]);
                        item.add(nums[j]);
                        item.add(nums[beforePos]);
                        item.add(nums[endPos]);
                        result.add(item);
                        beforePos++;
                        endPos--;
                        while(beforePos < endPos && nums[beforePos] == nums[beforePos - 1]){
                            beforePos++;
                        }
                        while(beforePos < endPos && nums[endPos] == nums[endPos + 1]){
                            endPos--;
                        }
                    }else if(nums[i] + nums[j] + nums[beforePos] + nums[endPos] < target){
                        beforePos++;
                    }else{
                        endPos--;
                    }
                }
            }
        }
        return result;
    }
}

19. 删除链表的倒数第N个节点

给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。

示例:

给定一个链表: 1->2->3->4->5, 和 n = 2.

当删除了倒数第二个节点后,链表变为 1->2->3->5.

说明:

给定的 n 保证是有效的。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        Map<Integer,ListNode> map = new HashMap();
        int num = 1;
        if(head != null){
            map.put(num,head);
        }else{
            return null;
        }
        ListNode l = head;
        while(l.next != null){
            ListNode next = l.next;
            num++;
            map.put(num,next);
            l = l.next;            
        }
        int pos = num - n;
        if(pos == 0){
            return num >= 2 ? map.get(2) : null;
        }
        ListNode node = map.get(pos);
        node.next = node.next.next;
        return head;
    }
}

20. 有效的括号

给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。

注意空字符串可被认为是有效字符串。

示例 1:

输入: “()”
输出: true

示例 2:

输入: “()[]{}”
输出: true

示例 3:

输入: “(]”
输出: false

示例 4:

输入: “([)]”
输出: false

示例 5:

输入: “{[]}”
输出: true

class Solution {
    public boolean isValid(String s) {
        Stack <Character> stack = new Stack();

        for(int i = 0; i < s.length(); i++ ){
            char a = s.charAt(i);
            switch(a){
                case'(':
                    stack.push('('); 
                    break;
                case'[':
                    stack.push('['); 
                    break;
                case'{':
                    stack.push('{'); 
                    break;
                case')':
                    if(stack.empty()){
                        return false;
                    }
                    char value = stack.pop();
                    if(value != '('){
                        return false;
                    }
                    break;
                case']':
                    if(stack.empty()){
                        return false;
                    }
                    char value1 = stack.pop();
                    if(value1 != '['){
                        return false;
                    }
                    break;
                case'}':
                    if(stack.empty()){
                        return false;
                    }
                    char value2 = stack.pop();
                    if(value2 != '{'){
                        return false;
                    }
                    break;
            }           
        }
        if(!stack.empty()){
            return false;
        }
        return true;
    }
}

21. 合并两个有序链表

将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

示例:

输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode head;
        ListNode pos;
        if(l1 != null && l2 != null){
            if(l1.val <= l2.val){
                head = l1;
                l1 = l1.next;
            }else{
                head = l2;
                l2 = l2.next;
            }
            pos = head;
        }else if(l1 == null && l2 != null){
            return l2;
        }else {
            return l1;
        }

        while(l1 != null && l2 != null){
            if(l1.val <= l2.val){
                pos.next = l1;
                l1 = l1.next;
                pos = pos.next;
            }else{
                pos.next = l2;
                l2 = l2.next;
                pos = pos.next;
            }
            
        }
        if(l1 == null && l2 != null){
            pos.next = l2;
        }else {
            pos.next = l1;
        }
        return head;
    }
}

22. 括号生成

给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。

例如,给出 n = 3,生成结果为:

[
“((()))”,
“(()())”,
“(())()”,
“()(())”,
“()()()”
]

class Solution {
    public List<String> generateParenthesis(int n) {
        List<String> result = new ArrayList();
        if(n == 0){
            return result;
        }
        if(n == 1){
            result.add("()");
            return result;
        }else{
            int nextSize = n-1;
            List<String> subString = generateParenthesis(nextSize);
            for(int i = 0; i< subString.size(); i++){
                result.addAll(findStr(subString.get(i),nextSize));
            }
            
        }
        return result;
    }
    private List<String> findStr(String s,int number){
        int size = number;
        List<Integer> position = new ArrayList();
        for(int j = 0; j < 2 * number; j++){
            if(s.charAt(j) == '('){
                size--;
            }
            if(size == 0 && s.charAt(j) == ')'){
                position.add(j);
            }
        }
        List<String> result = new ArrayList();
        for(int i = 0; i < position.size(); i++){           
            StringBuilder str = new StringBuilder();
            str.append(s.substring(0,position.get(i)));
            str.append("())");
            if(position.get(i) + 1 < number*2){
                str.append(s.substring(position.get(i) + 1,number*2));
            }
            result.add(str.toString());
        }

        result.add(new String(s+"()"));
        return result;
    }
}

23. 合并K个排序链表

合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。

示例:

输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists.length == 0){
            return null;
        }
        if(lists.length == 1){
            return lists[0];
        }
        int position = 1;
        ListNode l1 = lists[0];
        ListNode head;
        ListNode pos;
        while(position < lists.length){
            ListNode l2 = lists[position];
            if(l1 != null && l2 != null){
                if(l1.val <= l2.val){
                    head = l1;
                    l1 = l1.next;
                }else{
                    head = l2;
                    l2 = l2.next;
                }
                pos = head;
            }else if(l1 == null && l2 != null){
                l1 = l2;
                position++;
                continue;
            }else {
                position++;
                continue;
            }
            while(l1 != null && l2 != null){
                if(l1.val <= l2.val){
                    pos.next = l1;
                    l1 = l1.next;
                    pos = pos.next;
                }else{
                    pos.next = l2;
                    l2 = l2.next;
                    pos = pos.next;
                }
            
            }
            if(l1 == null && l2 != null){
                pos.next = l2;
            }else {
                pos.next = l1;
            }
            l1 = head;
            position++;           

        }
        
        return l1;    
    }
}

24. 两两交换链表中的节点

给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。

你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

示例:

给定 1->2->3->4, 你应该返回 2->1->4->3.

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode swapPairs(ListNode head) {
        if(head == null){
            return null;
        }
        ListNode positionFirst = head;
        ListNode positionSecond = head;
        boolean first = true;
        while(positionFirst != null){
            if(positionFirst.next == null){
                break;
            }
            if(!first){
                positionSecond.next = positionFirst.next;
            }            
            positionSecond = positionFirst.next;
            positionFirst.next = positionSecond.next;
            positionSecond.next = positionFirst;
            if(first){
                head = positionSecond;
                first = false;
            }
            positionFirst = positionFirst.next;
            positionSecond = positionSecond.next;
        }
        return head;
    }
}

25. K 个一组翻转链表

给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。

k 是一个正整数,它的值小于或等于链表的长度。

如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

示例 :

给定这个链表:1->2->3->4->5

当 k = 2 时,应当返回: 2->1->4->3->5

当 k = 3 时,应当返回: 3->2->1->4->5

说明 :

你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        if(k == 0 || k == 1){
            return head;
        }
        Stack<ListNode> stack = new Stack();
        ListNode p = head;
        ListNode connector = new ListNode(0);
        connector.next = head;
        ListNode begin = connector;
        int number;
        while(p != null){   
            number = k;        
            while(number > 0 && p != null){
                stack.push(p);
                number--;
                p = p.next;
            }
            if(number == 0){
                while(!stack.isEmpty()){
                    connector.next = stack.pop();
                    connector = connector.next;
                }
                connector.next = p;
            }
            
        }
        return begin.next;
    }
}

26. 删除排序数组中的重复项

给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。

不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

示例 1:

给定数组 nums = [1,1,2],

函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。

你不需要考虑数组中超出新长度后面的元素。

示例 2:

给定 nums = [0,0,1,1,1,2,2,3,3,4],

函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。

你不需要考虑数组中超出新长度后面的元素。

说明:

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以“引用”方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

你可以想象内部操作如下:

// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
int len = removeDuplicates(nums);

// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。
for (int i = 0; i < len; i++) {
print(nums[i]);
}

class Solution {
    public int removeDuplicates(int[] nums) {
        if(nums.length == 0){
            return 0;
        }
        int beforeVal = nums[0];
        int position = 1;
        for(int i = 1; i < nums.length; i++){
            if(beforeVal != nums[i]){
                nums[position] = nums[i];
                position++;
                beforeVal = nums[i];
            }
        }
        return position;
    }
}

27. 移除元素

给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。

不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

示例 1:

给定 nums = [3,2,2,3], val = 3,

函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。

你不需要考虑数组中超出新长度后面的元素。

示例 2:

给定 nums = [0,1,2,2,3,0,4,2], val = 2,

函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。

注意这五个元素可为任意顺序。

你不需要考虑数组中超出新长度后面的元素。

class Solution {
    public int removeElement(int[] nums, int val) {
        int size = nums.length;
        int before = 0;
        int end = nums.length - 1;

        while (before <= end){
            if(before == end && nums[before] == val){
                return before;
            }
            while(before < nums.length && nums[before] != val){
                before ++;
            }
            while( end >= 0 && nums[end] == val){
                size--;
                end --;
            }
            if(before < end){
                size--;
                nums[before] = nums[end];
                nums[end] = val;
                before ++;
                end--;
            }
        }
        return size;
    }
}

28. 实现 strStr()

实现 strStr() 函数。

给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。

示例 1:

输入: haystack = “hello”, needle = “ll”
输出: 2

示例 2:

输入: haystack = “aaaaa”, needle = “bba”
输出: -1

说明:

当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。

对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。

class Solution {
    public int strStr(String haystack, String needle) {
        if(needle.length() == 0){
            return 0;
        }
        int result = -1;
        int compareLength = needle.length();
        char compare = needle.charAt(0);
        for(int i = 0; i < haystack.length(); i++){
            if(haystack.charAt(i) == compare){
                if(i+compareLength > haystack.length()){
                    break;
                }
                String sub = haystack.substring(i,i+compareLength);
                if(sub.equals(needle)){
                    result = i;
                    break;
                }
            }
        }
        return result;
    }
}

30. 串联所有单词的子串

给定一个字符串 s 和一些长度相同的单词 words。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。

注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。

示例 1:

输入:
s = “barfoothefoobarman”,
words = [“foo”,“bar”]
输出:[0,9]
解释:
从索引 0 和 9 开始的子串分别是 “barfoor” 和 “foobar” 。
输出的顺序不重要, [9,0] 也是有效答案。
示例 2:

输入:
s = “wordgoodgoodgoodbestword”,
words = [“word”,“good”,“best”,“word”]
输出:[]

class Solution {
    public List<Integer> findSubstring(String s, String[] words) {
        List<Integer> range = new ArrayList();
        if(words.length == 0){
            return range;
        }
        int size = words[0].length();
        //realMap
        Map<String,Integer> wordsMap = new HashMap();      
        for(int i = 0; i < words.length; i++){
            if(wordsMap.get(words[i]) == null){
                wordsMap.put(words[i],1);
            }else{
                wordsMap.put(words[i],1 + wordsMap.get(words[i]));
            }            
        }
        int last = size;
        int begin = 0;
        int last2;
        int begin2;
        int times = words.length;
        while(last <= s.length()){
            Map<String,Integer> newMap = new HashMap();
            last2 = last;
            begin2 = begin;
            String sub = s.substring(begin2,last2);
            while(wordsMap.get(sub) != null && last2 <= s.length() && times > 0){
                sub = s.substring(begin2,last2);
                if(newMap.get(sub) == null){
                    newMap.put(sub,1);
                }else{
                    newMap.put(sub,1 + newMap.get(sub));
                }   
                begin2 += size;
                last2 += size;
                times -= 1;
                if(last2 > s.length()){
                    break;
                }
            }
            if(wordsMap.size() == newMap.size()){
                boolean flag = true;
                for(Map.Entry<String,Integer> entry:newMap.entrySet()){
                    if(entry.getValue() != wordsMap.get(entry.getKey())){
                        flag = false;
                        break;
                    }
                }
                if(flag){
                    range.add(begin);
                }         
            }
            times = words.length;
            begin += 1;
            last += 1;
        }
        return range;
    }
}

31. 下一个排列

实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。

如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。

必须原地修改,只允许使用额外常数空间。

以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1

class Solution {
    public void nextPermutation(int[] nums) {
        int size = nums.length;
        if(size == 0){
            return ;
        }

        int max = nums[size - 1];
        int exchange = size - 1;
        
        //记录发现第一个递减值的位置
        int position = -1;
        int now = -1;
        for(int i = size-1; i >= 0; i--){
            if(max <= nums[i]){
                max = nums[i];
                exchange = i;
            }else{
                position = i;
                now = nums[i];
                break;
            }
        }
        

        for(int i = position + 1; i < size && position != -1; i++){
            if(nums[i] <= max && nums[i] > now){
                max = nums[i];
                exchange = i;
            }
        }

        if(exchange != -1 && position != -1){
            nums[position] = max;
            nums[exchange] = now;
        }

        for(int i = position + 1,j = size -1;i<j;i++,j--){
            int temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
        }
       
    }
  
}

32.最长有效括号

给定一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长的包含有效括号的子串的长度。

示例 1:

输入: “(()”
输出: 2
解释: 最长有效括号子串为 “()”
示例 2:

输入: “)()())”
输出: 4
解释: 最长有效括号子串为 “()()”

class Solution {
    public int longestValidParentheses(String s) {
        Stack<Character> stack = new Stack();
        Stack<Character> temp = new Stack();
        int max = 0;
        for(int i = 0; i < s.length(); i++){
            char now = s.charAt(i);
            if(now == '('){
                stack.push('(');
            }else{
                boolean flag = false;
                while(!stack.isEmpty()){
                    char before = stack.pop();
                    if(before == '('){
                        stack.push('*');
                        flag = true;
                        break;
                    }else if(before == '*'){
                        temp.push(before);
                        continue;
                    }else{
                        stack.push(')');
                        break;
                    }
                }
                while(!temp.isEmpty()){
                    stack.push(temp.pop());
                }  
                if(!flag){
                    stack.push(')');
                }
                             
            }
        }
        int count = 0;
        while(!stack.isEmpty()){
            char a = stack.pop();
            if(a=='*'){
                count += 2;
            }else{
                max = max > count ? max : count;
                count = 0;
            }
        }
        max = max > count ? max : count;
        return max;
    }

}

33. 搜索旋转排序数组

假设按照升序排序的数组在预先未知的某个点上进行了旋转。

( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。

搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。

你可以假设数组中不存在重复的元素。

你的算法时间复杂度必须是 O(log n) 级别。

示例 1:

输入: nums = [4,5,6,7,0,1,2], target = 0
输出: 4
示例 2:

输入: nums = [4,5,6,7,0,1,2], target = 3
输出: -1

class Solution {
    public int search(int[] nums, int target) {
        int result = -1;
        int before = 0; 
        int end = nums.length -1 ;
        int harf;
        while(before <= end){    
            harf = (end - before) / 2 + before;
            if(before == harf && nums[before] != target && nums[end] != target){
                break;
            }
            if(nums[before] == target){
                result = before;
                break;
            }
            if(nums[end] == target){
                result = end;
                break;
            }
            if(nums[before] > target && nums[end] < target){
                break;
            }
            if(nums[before] > target && nums[end] > target){
                if(nums[harf] > nums[end]){
                    before = harf;
                }else if(nums[harf] > target){
                    end = harf;
                }else{
                    before = harf;
                }
                continue;
            }
            if(nums[before] < target && nums[end] < target){
                if(nums[harf] < nums[before]){
                    end = harf;
                }else if(nums[harf] > target){
                    end = harf;
                }else{
                    before = harf;
                }
                continue;
            }
            if(target >= nums[harf]){
                before = harf;
            }else{
                end = harf;
            }
        }
        return result;        
    }
}

34.在排序数组中查找元素的第一个和最后一个位置

给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。

你的算法时间复杂度必须是 O(log n) 级别。

如果数组中不存在目标值,返回 [-1, -1]。

示例 1:

输入: nums = [5,7,7,8,8,10], target = 8
输出: [3,4]
示例 2:

输入: nums = [5,7,7,8,8,10], target = 6
输出: [-1,-1]

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int[] result = new int[2];
        result[0] = -1;
        result[1] = -1;
        int before = 0;
        int end = nums.length - 1;
        if(end < before || target < nums[before] || target > nums[end]){
            return result;
        }
        int harf; 
        boolean flag = false;
        while(before <= end){
            if( end-before <= 1 && nums[before] != target && nums[end] != target){
                break;
            }
            if( end-before <= 1 && (nums[before] != target && nums[end] == target)){
                result[0] = end;
                result[1] = end;
                break;
            }
            harf = (end -before) / 2 + before; 
            if(nums[harf] < target){
                before = harf;
            }else if(nums[harf] > target){
                end = harf;
            }else{
                flag = true;
                break;
            }           
        }
        if(!flag){
            return result;
        }
        result[0]=findPos(nums,before,end,target,1);
        result[1]=findPos(nums,before,end,target,2);
        return result;
    }
    public int findPos(int[] nums, int before,int end,int target ,int type){
        int mid = (end - before)/2 + before;
        while(before < end){
            
            if(nums[mid] > target || (target == nums[mid] && type == 1)){
                end = mid;
            }else{
                before = mid+1;
            }
            mid = (end - before)/2 + before;
        }
        if(type == 2 && nums[before]!=target){
            return before-1;
        }
        return before;
    }
}

35. 搜索插入位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

你可以假设数组中无重复元素。

示例 1:

输入: [1,3,5,6], 5
输出: 2
示例 2:

输入: [1,3,5,6], 2
输出: 1
示例 3:

输入: [1,3,5,6], 7
输出: 4
示例 4:

输入: [1,3,5,6], 0
输出: 0

class Solution {
    public int searchInsert(int[] nums, int target) {
        int before = 0;
        int end = nums.length - 1;
        if(nums[before] > target || nums.length == 0){
            return 0;
        }
        if(nums[end]<target){
            return nums.length;
        }
        int mid = (end - before) /2 + before;
        while(end >= before){
            if(end == before){
                break;
            }
            if(nums[mid] > target){
                end = mid;
            }else if(nums[mid] < target){
                before = mid + 1;
            }else if(nums[mid]==target){
                break;
            }
            mid = (end - before) /2 + before;
        }
        return mid;
    }
}

36. 有效的数独

判断一个 9x9 的数独是否有效。只需要根据以下规则,验证已经填入的数字是否有效即可。

数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。

上图是一个部分填充的有效的数独。

数独部分空格内已填入了数字,空白格用 ‘.’ 表示。

示例 1:

输入:
[
[“5”,“3”,".",".",“7”,".",".",".","."],
[“6”,".",".",“1”,“9”,“5”,".",".","."],
[".",“9”,“8”,".",".",".",".",“6”,"."],
[“8”,".",".",".",“6”,".",".",".",“3”],
[“4”,".",".",“8”,".",“3”,".",".",“1”],
[“7”,".",".",".",“2”,".",".",".",“6”],
[".",“6”,".",".",".",".",“2”,“8”,"."],
[".",".",".",“4”,“1”,“9”,".",".",“5”],
[".",".",".",".",“8”,".",".",“7”,“9”]
]
输出: true
示例 2:

输入:
[
[“8”,“3”,".",".",“7”,".",".",".","."],
[“6”,".",".",“1”,“9”,“5”,".",".","."],
[".",“9”,“8”,".",".",".",".",“6”,"."],
[“8”,".",".",".",“6”,".",".",".",“3”],
[“4”,".",".",“8”,".",“3”,".",".",“1”],
[“7”,".",".",".",“2”,".",".",".",“6”],
[".",“6”,".",".",".",".",“2”,“8”,"."],
[".",".",".",“4”,“1”,“9”,".",".",“5”],
[".",".",".",".",“8”,".",".",“7”,“9”]
]
输出: false
解释: 除了第一行的第一个数字从 5 改为 8 以外,空格内其他数字均与 示例1 相同。
但由于位于左上角的 3x3 宫内有两个 8 存在, 因此这个数独是无效的。
说明:

一个有效的数独(部分已被填充)不一定是可解的。
只需要根据以上规则,验证已经填入的数字是否有效即可。
给定数独序列只包含数字 1-9 和字符 ‘.’ 。
给定数独永远是 9x9 形式的。

class Solution {
    public boolean isValidSudoku(char[][] board) {
        for(int i = 0; i < 9; i++){
            Set<Character> set = new HashSet();
            Set<Character> set2 = new HashSet();
            for(int j = 0; j < 9; j++){
                if(board[i][j] != '.'){
                    if(set.contains(board[i][j])){
                        return false;
                    }
                    set.add(board[i][j]);
                }

                if(board[j][i] != '.'){
                    if(set2.contains(board[j][i])){
                        return false;
                    }
                    set2.add(board[j][i]);
                }
            }
        }
        for(int i = 0; i < 9; i = i+3){
            for(int m = 0; m < 9; m=m+3){
                Set<Character> set = new HashSet();
                for(int j = i; j < i+3; j++){
                for(int k = m; k < m+3; k++){
                    if(board[k][j] != '.'){
                         if(set.contains(board[k][j])){
                             return false;
                         }
                         set.add(board[k][j]);
                    }
                }
            }
            }
        }

        return true;

        
    }
}

37. 解数独

编写一个程序,通过已填充的空格来解决数独问题。

一个数独的解法需遵循如下规则:

数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
空白格用 ‘.’ 表示。

一个数独。

答案被标成红色。

Note:

给定的数独序列只包含数字 1-9 和字符 ‘.’ 。
你可以假设给定的数独只有唯一解。
给定数独永远是 9x9 形式的。

class Solution {
    public void solveSudoku(char[][] board) {   
       System.out.println(search(board,0,0));
    }

    public boolean search(char[][] board,int x,int y){
        for(int i = x; i < 9;i++){
            int j = 0;
            if(i == x){
                j = y;
            }
            for(; j < 9; j++){                
                if(board[i][j] == '.'){
                    Set set = findOnly(board,i,j);
                    if(set.size() == 0){
                        return false;
                    }
                    Iterator iterator = set.iterator();
                    while(iterator.hasNext()){
                        int a = (Integer)iterator.next();
                        board[i][j] = (char) a;
                        if(search(board,i,j+1)){ 
                            return true;
                        }else{
                            board[i][j] = '.';
                        }
                    }
                    if(board[i][j] == '.'){
                        return false;
                    }
                }
            }
        }
        return true;
    }

    public Set findOnly(char[][] board,int x,int y){
        Set set = new HashSet();
        for(int i = 49; i <= 57; i++){
            set.add(i);
        }
        int squrex = (x/3) * 3;
        int squrey = (y/3) * 3;
        
        //遍历行
        for(int i = 0; i < 9; i++){
            if(board[x][i] != '.'){
                set.remove((int)board[x][i]);
            }
            if(board[i][y] != '.'){
                set.remove((int)board[i][y]);
            }
        }
        
        for(int i = squrex;i<squrex+3;i++){
            for(int j =squrey;j<squrey+3;j++){
                if(board[i][j] != '.'){
                    set.remove((int)board[i][j]);
                }
            }
        }        
        return set;
    }
}

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 项。

注意:整数顺序将表示为一个字符串。

示例 1:

输入: 1
输出: “1”
示例 2:

输入: 4
输出: “1211”

class Solution {
    public String countAndSay(int n) {
        String before = "1";
        int count = 1;
        char cb = '1';
        while(n > 1){
            StringBuilder str = new StringBuilder();
            cb = before.charAt(0);
            for(int i = 1; i < before.length(); i++){
                if(cb == before.charAt(i)){
                    count ++;
                }else{
                    str.append(count); 
                    str.append(cb);
                    cb = before.charAt(i);
                    count = 1;                    
                }
            }
            str.append(count);
            str.append(cb);
            count = 1;
            n--;
            before = str.toString();
        }
        return before;
        
    }

}

39. 组合总和

给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的数字可以无限制重复被选取。

说明:

所有数字(包括 target)都是正整数。
解集不能包含重复的组合。
示例 1:

输入: candidates = [2,3,6,7], target = 7,
所求解集为:
[
[7],
[2,2,3]
]
示例 2:

输入: candidates = [2,3,5], target = 8,
所求解集为:
[
[2,2,2,2],
[2,3,3],
[3,5]
]

class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> results = new ArrayList();
        Arrays.sort(candidates);
        return find(candidates, target,0);
    }
    public List<List<Integer>> find(int[] candidates, int target,int now) {
        List<List<Integer>> results = new ArrayList();
        for(int i = now; i < candidates.length; i++){
            if(candidates[i] < target){
                List<List<Integer>> lists = find(candidates,target-candidates[i],i);
                for(int j = 0;j<lists.size();j++){
                    List newlist = lists.get(j);
                    newlist.add(0,candidates[i]);
                    results.add(newlist);
                }
            }else if(candidates[i]==target){
                List list = new ArrayList();
                list.add(0,candidates[i]);
                results.add(list);
            }else{
                break;
            }
        }
        return results;
    }
    
}

40. 组合总和 II

给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用一次。

说明:

所有数字(包括目标数)都是正整数。
解集不能包含重复的组合。
示例 1:

输入: candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
示例 2:

输入: candidates = [2,5,2,1,2], target = 5,
所求解集为:
[
[1,2,2],
[5]
]

class Solution {
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        List<List<Integer>> results = new ArrayList();
        if(candidates.length == 0){
            return results;
        }
        Arrays.sort(candidates);
        return find(candidates,target,0,-1);
    }
    public List<List<Integer>> find(int[] candidates, int target,int nowPos,int nowVal) {
        List<List<Integer>> results = new ArrayList();
        int compare = 0;
        for(int i = nowPos; i < candidates.length; i++){
            if(i == nowPos){
                compare = candidates[nowPos];
            }else if(candidates[i] == compare || (i > nowPos && candidates[i] ==nowVal)){
                continue;
            }else{
                compare = candidates[i];
            }
            if(candidates[i] < target){
                List<List<Integer>> lists = find(candidates,target-candidates[i],i+1,candidates[i]);
                for(int j = 0;j<lists.size();j++){
                    List newlist = lists.get(j);
                    newlist.add(0,candidates[i]);
                    results.add(newlist);
                }
            }else if(candidates[i]==target){
                List list = new ArrayList();
                list.add(0,candidates[i]);
                results.add(list);
            }else{
                break;
            }
        }
        return results;
    }
   
}

41. 缺失的第一个正数

给定一个未排序的整数数组,找出其中没有出现的最小的正整数。

示例 1:

输入: [1,2,0]
输出: 3
示例 2:

输入: [3,4,-1,1]
输出: 2
示例 3:

输入: [7,8,9,11,12]
输出: 1

class Solution {
    public int firstMissingPositive(int[] nums) {
        Map<Integer,Integer> map = new HashMap();
        for(int i = 0; i < nums.length; i++){
            map.put(nums[i],nums[i]);
        }
        boolean flag = false;
        int a = 1;
        while(!flag){
            if(map.get(a) == null){
                flag = true;
            }else{
                a++;
            } 
        }
        return a;
    }
}

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

class Solution {
    public int trap(int[] height) {
        int result = 0;
        boolean findBefore = false;
        int beforePos = 0;
        int beforeVal = 0;
        int lower = 0;
        for(int i = 0; i < height.length; i++){
            if(!findBefore && height[i] == 0){
                continue;
            }
            if(!findBefore && height[i] != 0){
                beforePos = i;
                beforeVal = height[i];
                findBefore = true;
                lower = height[i];
                continue;
            }
            lower = height[i] < lower? height[i] : lower;
            
            if(height[i] > lower && lower < beforeVal){
                int compare = beforeVal < height[i] ? beforeVal : height[i];
                result += cal(beforePos,i,height,compare);
                lower = compare;
                if(beforeVal <= height[i]){
                    beforePos = i;
                    beforeVal = height[i];
                    lower = height[i];
                }
            }else if(height[i] > lower && lower == beforeVal){
                beforePos = i;
                beforeVal = height[i];
                lower = height[i];
            }
        }
        return result;
    }
    public int cal(int beforePos,int endPos,int[] height ,int compare){
        int sum = 0;
        for(int i = beforePos + 1; i < endPos; i++){
            if(height[i] >= compare){
                continue;
            }
            sum += compare-height[i];
            height[i] = compare;
        }
        return sum;
    }
}

43. 字符串相乘

给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。

示例 1:

输入: num1 = “2”, num2 = “3”
输出: “6”
示例 2:

输入: num1 = “123”, num2 = “456”
输出: “56088”
说明:

num1 和 num2 的长度小于110。
num1 和 num2 只包含数字 0-9。
num1 和 num2 均不以零开头,除非是数字 0 本身。
不能使用任何标准库的大数类型(比如 BigInteger)或直接将输入转换为整数来处理。

class Solution {
    public String multiply(String num1, String num2) {
        int maxsize = num1.length() + num2.length();
        int[] result = new int[maxsize];
        int i = num1.length() - 1;
        int j = num2.length() - 1;
        int pos = maxsize - 1;
        int leave = 0;
        int sum = 0;
        while (j >= 0) {
            while (i >= 0) {
                int a = (int) num1.charAt(i) - 48;
                sum = ((int) num1.charAt(i) - 48) * ((int) num2.charAt(j) - 48) + leave + result[pos];
                leave = sum / 10;
                result[pos] =sum % 10;
                i--;
                pos--;
            }
            j --;
            result[pos] += leave;
            leave = 0;
            i= num1.length()-1;
            pos = pos + num1.length() - 1;
        }

        boolean first = false;
        StringBuilder str = new StringBuilder();
        for (int k = 0; k < maxsize; k++) {
            if (!first && result[k] == 0) {
                continue;
            }
            if (!first && result[k] != 0) {
                first = true;
            }
            str.append(result[k]);
        }
        if(str.length() == 0){
            str.append(0);
        }

        return str.toString();

    }
}

45. 跳跃游戏 II

给定一个非负整数数组,你最初位于数组的第一个位置。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

你的目标是使用最少的跳跃次数到达数组的最后一个位置。

示例:

输入: [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。
从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。
说明:

假设你总是可以到达数组的最后一个位置。

class Solution {
    public int jump(int[] nums) {
        int size = nums.length;
        if(size <= 1){
            return 0;
        }
        int[] jump = new int[size];
        for(int i = 0; i < size - 1; i++){
            jump[i] = Integer.MAX_VALUE - 1;
        }
        jump[size - 1] = 0;
        for(int i = size -2; i >= 0; i--){
            for(int j = i + 1; j <= i + nums[i]  &&  j < size; j++ ){
                jump[i] = jump[i] < 1 +jump[j] ? jump[i] : jump[j]+1;
            }
        }

        return jump[0];
        
    }
}

46. 全排列

给定一个没有重复数字的序列,返回其所有可能的全排列。

示例:

输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]

class Solution {
    public List<List<Integer>> permute(int[] nums) {
        int[] select = new int[nums.length];
        if(nums.length == 0){
            List<List<Integer>> results = new ArrayList();
            List<Integer> result = new ArrayList();
            results.add(result);
            return results;
        }
        return get(nums,select);
    }
    public List<List<Integer>> get(int[] nums,int[] select) {
        List<List<Integer>> results = new ArrayList();
        for(int i = 0; i < nums.length ; i++){
            if(select[i] == 1){
                continue;
            }
            select[i] = 1;
            List<List<Integer>> lists = get(nums,select);
            if(lists.size() == 0){
                List<Integer> list = new ArrayList();
                lists.add(list);
            }
            for(int j = 0; j < lists.size(); j++){
                lists.get(j).add(nums[i]);
            }
            results.addAll(lists);
            select[i] = 0;           
        }  
        return results; 
    }
    
}

47. 全排列 II

给定一个可包含重复数字的序列,返回所有不重复的全排列。

示例:

输入: [1,1,2]
输出:
[
[1,1,2],
[1,2,1],
[2,1,1]
]

class Solution {
    public List<List<Integer>> permuteUnique(int[] nums) {
        Arrays.sort(nums);
        int[] select = new int[nums.length];  
        return get(nums,select);
    }
    public List<List<Integer>> get(int[] nums,int[] select) {
        List<List<Integer>> results = new ArrayList();
        for(int i = 0; i < nums.length ; i++){
            if(select[i] == 1 || (i > 0 && nums[i] == nums[i - 1] && select[i-1] == 0)){
                continue;
            }
            select[i] = 1;
            List<List<Integer>> lists = get(nums,select);
            if(lists.size() == 0){
                List<Integer> list = new ArrayList();
                lists.add(list);
            }
            for(int j = 0; j < lists.size(); j++){
                lists.get(j).add(nums[i]);
            }
            results.addAll(lists);
            select[i] = 0;           
        }  
        return results; 
    }
    
}

49. 字母异位词分组

给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。

示例:

输入: [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”],
输出:
[
[“ate”,“eat”,“tea”],
[“nat”,“tan”],
[“bat”]
]
说明:

所有输入均为小写字母。
不考虑答案输出的顺序。

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        List<List<String>> result = new ArrayList();
        Map<List<Integer>,List<String>> temp = new HashMap();
       
        for(int i = 0; i < strs.length; i++){
            String s = strs[i];
            ArrayList<Integer> list = new ArrayList();
            for(int j = 0 ; j < s.length(); j++){
                int a =s.charAt(j);
                list.add(a);
            }
            Collections.sort(list);
            List<String> strings = temp.get(list);
            if(strings == null){
                strings = new ArrayList();
            }
            strings.add(s);
            temp.put(list,strings);
        }
        for(List<String> s : temp.values()){
            result.add(s);
        }
        return result;
    }
}

51&52 N皇后

n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

上图为 8 皇后问题的一种解法。

给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。

每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。

示例:

输入: 4
输出: [
[".Q…", // 解法 1
“…Q”,
“Q…”,
“…Q.”],

["…Q.", // 解法 2
“Q…”,
“…Q”,
“.Q…”]
]
解释: 4 皇后问题存在两个不同的解法。

class Solution {
   public List<List<String>> solveNQueens(int n) {
        List<List<String>> resuls = new ArrayList();
        List<String> now = new ArrayList<>();
        if (n > 0) {
            solve(resuls, now, 0, n);
        }
        return resuls;
    }
a
    private void solve(List<List<String>> results, List<String> now, int row, int n) {
        for (int j = 0; j < n; j++) {
            if (check(now, row, j, n)) {a
                now.add(getString(j, n));
                if (row == n - 1) {
                    List<String> strings = new ArrayList<>();
                    strings.addAll(now);
                    results.add(strings);
                    now.remove(row);
                }
                if (row < n - 1) {
                    solve(results, now, row + 1, n);
                    now.remove(row);
                }
            }
        }
    }
    private  boolean check(List<String> now, int x, int y, int n) {
        for (int i = 0; i < now.size(); i++) {
            if (now.get(i).charAt(y) == 'Q' ||
                    (y + i - x >= 0 && y + i - x < y && now.get(i).charAt(y + i - x) == 'Q') ||
                    (y - i + x > y && y - i + x < n && now.get(i).charAt(y - i + x) == 'Q')) {
                return false;
            }
        }
        return true;
    }

    private String getString(int j, int n) {
        StringBuilder stringBuilder = new StringBuilder();
        for (int k = 0; k < n; k++) {
            if (k == j) {
                stringBuilder.append("Q");
            } else {
                stringBuilder.append(".");
            }
        }
        return stringBuilder.toString();
    }
}

53. 最大子序和

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

示例:

输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
进阶:

class Solution {
    public int maxSubArray(int[] nums) {
        int result = nums[0];
        int sum = 0;
        for (int num : nums) {
            if (sum > 0){
                sum += num;
            }else{
                sum = num;
            }               
            result =result>sum?result:sum;
        }
        return result;
    }
}

54. 螺旋矩阵

给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。

示例 1:

输入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
输出: [1,2,3,6,9,8,7,4,5]
示例 2:

输入:
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9,10,11,12]
]
输出: [1,2,3,4,8,12,11,10,9,5,6,7]

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> result = new ArrayList<>();
        int rownum = matrix.length;
        if (rownum == 0) {
            return result;
        }
        int columnnum = matrix[0].length;

        if (columnnum == 0) {
            return result;
        }
        int[][] check = new int[rownum][columnnum];
        result.addAll(check(rownum, columnnum, matrix, check, 0, 0, -1));
        return result;

    }

    public List<Integer> check(int rownum, int column, int[][] matrix, int[][] check, int type, int x, int y) {
        List<Integer> result = new ArrayList<>();
        boolean findnext = false;
        type = type % 4;
        if (type == 0) {
            y++;
            while (y < column && check[x][y] == 0) {
                findnext = true;
                result.add(matrix[x][y]);
                check[x][y] = -1;
                y++;
            }
            y--;
        } else if (type == 1) {
            x++;
            while (x < rownum && check[x][y] == 0) {
                findnext = true;
                result.add(matrix[x][y]);
                check[x][y] = -1;
                x++;
            }
            x--;
        }else if (type == 2) {
            y--;
            while (y >= 0  && check[x][y] == 0) {
                findnext = true;
                result.add(matrix[x][y]);
                check[x][y] = -1;
                y--;
            }
            y++;
        }else{
            x--;
            while (x >= 0 && check[x][y] == 0) {
                findnext = true;
                result.add(matrix[x][y]);
                check[x][y] = -1;
                x--;
            }
            x++;
        }
        if(findnext){
            result.addAll(check(rownum, column, matrix, check, ++type, x, y));
        }
        return result;

    }
}

56.合并区间

给出一个区间的集合,请合并所有重叠的区间。

示例 1:

输入: [[1,3],[2,6],[8,10],[15,18]]
输出: [[1,6],[8,10],[15,18]]
解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
示例 2:

输入: [[1,4],[4,5]]
输出: [[1,5]]
解释: 区间 [1,4] 和 [4,5] 可被视为重叠区间。

class Solution {
     class Node implements Comparable<Node>{
        private Integer before;
        private Integer end;

        public Node(Integer before, Integer end) {
            this.before = before;
            this.end = end;
        }

        public Integer getBefore() {
            return before;
        }

        public void setBefore(Integer before) {
            this.before = before;
        }

        public Integer getEnd() {
            return end;
        }

        public void setEnd(Integer end) {
            this.end = end;
        }

        @Override
        public int compareTo(Node o) {
            if(this.before.compareTo(o.getBefore())!=0){
                return this.before.compareTo(o.getBefore());
            }
            return this.end.compareTo(o.getEnd());

        }

    }
    public int[][] merge(int[][] intervals) {
       Set<Node> nodes = new TreeSet<>();
        List<Node> nodeList = new ArrayList<>();
        for(int i = 0; i< intervals.length;i++){
            Node node = new Node(intervals[i][0],intervals[i][1]);
            nodes.add(node);
        }
        Iterator it = nodes.iterator();
        Node node;
        Node compareNode;
        while(it.hasNext()){
            node = (Node) it.next();
            if(nodeList.size() == 0){
                nodeList.add(new Node(node.getBefore(),node.getEnd()));
                continue;
            }
            compareNode = nodeList.get(nodeList.size() - 1);
            if(node.getBefore() > compareNode.getEnd()){
                nodeList.add(new Node(node.getBefore(),node.getEnd()));
            }else if(node.getEnd() > compareNode.getEnd()){
                nodeList.add(new Node(compareNode.getBefore(),node.getEnd()));
                nodeList.remove(nodeList.size() - 2);
            }

        }
        int size = nodeList.size();
        int[][] result = new int[size][2];
        for(int i = 0 ; i < size; i++){
            result[i][0] = nodeList.get(i).getBefore();
            result[i][1] = nodeList.get(i).getEnd();
        }
        return result;

    }
}

57.插入区间

给出一个无重叠的 ,按照区间起始端点排序的区间列表。

在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。

示例 1:

输入: intervals = [[1,3],[6,9]], newInterval = [2,5]
输出: [[1,5],[6,9]]
示例 2:

输入: intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8]
输出: [[1,2],[3,10],[12,16]]
解释: 这是因为新的区间 [4,8] 与 [3,5],[6,7],[8,10] 重叠。

class Solution {
    class Node implements Comparable<Node> {
        private Integer before;
        private Integer end;

        public Node(Integer before, Integer end) {
            this.before = before;
            this.end = end;
        }

        public Integer getBefore() {
            return before;
        }

        public void setBefore(Integer before) {
            this.before = before;
        }

        public Integer getEnd() {
            return end;
        }

        public void setEnd(Integer end) {
            this.end = end;
        }

        @Override
        public int compareTo(Node o) {
            if (this.before.compareTo(o.getBefore()) != 0) {
                return this.before.compareTo(o.getBefore());
            }
            return this.end.compareTo(o.getEnd());

        }

    }
    public int[][] insert(int[][] intervals, int[] newInterval) {
        Set<Node> nodeList = new TreeSet<>();
        if (newInterval.length == 0) return intervals;
        int before = newInterval[0];
        int end = newInterval[1];
        int compareBefore = 0;
        int compareEnd = 0;

        for (int i = 0; i < intervals.length; i++) {
            compareBefore = intervals[i][0];
            compareEnd = intervals[i][1];
            if (compareEnd < before || compareBefore > end) {
                nodeList.add(new Node(compareBefore, compareEnd));
            } else if (compareBefore < before && compareEnd <= end) {
                before = compareBefore;
            } else if (compareBefore < before && compareEnd > end) {
                before = compareBefore;
                end = compareEnd;
            } else if (compareBefore <= end && compareEnd > end) {
                end = compareEnd;
            }
        }
        nodeList.add(new Node(before, end));

        int size = nodeList.size();
        int[][] result = new int[size][2];
        Iterator iterator = nodeList.iterator();
        int i = 0;
        while (iterator.hasNext()) {
            Node node = (Node) iterator.next();
            result[i][0] = node.getBefore();
            result[i][1] = node.getEnd();
            i++;
        }
        return result;

    }
}

58. 最后一个单词的长度

给定一个仅包含大小写字母和空格 ’ ’ 的字符串,返回其最后一个单词的长度。

如果不存在最后一个单词,请返回 0 。

说明:一个单词是指由字母组成,但不包含任何空格的字符串。

示例:

输入: “Hello World”
输出: 5

class Solution {
    public int lengthOfLastWord(String s) {
        if(s.length() == 0 ){
            return 0;
        }
        String[] strings = s.split(" ");
        if(strings.length == 0){
            return 0;
        }
        String sss = strings[strings.length-1];
        return sss.length();
    }
}

59. 螺旋矩阵 II

给定一个正整数 n,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。

示例:

输入: 3
输出:
[
[ 1, 2, 3 ],
[ 8, 9, 4 ],
[ 7, 6, 5 ]
]

class Solution {
    public int[][] generateMatrix(int n) {
        int[][] status = new int[n][n];
        int[][] result = new int[n][n];
        int pos = 0;
        findPosition(result,status,0,-1,n,pos,1);
        return result;
    }
    public int[][] findPosition(int[][] result,int[][] status,int x,int y ,int n,int pos,int number){
        if(number>n*n){
            return result;
        }
        switch(pos){
            case 0:
                y++;
                break;
            case 1:
                x++;
                break;
            case 2:
                y--;
                break;
            case 3:
                x--;
                break;
        }
        if(y<n && y>=0 && x<n && x>=0 && status[x][y]==0){
            status[x][y]=1;
            result[x][y]=number;

        }else{
            switch(pos){
                case 0:
                    y--;
                    break;
                case 1:
                    x--;
                    break;
                case 2:
                    y++;
                    break;
                case 3:
                    x++;
                    break;
            }
            pos = (pos+1)%4;
            return findPosition(result,status,x,y,n,pos,number);
        }
        number++;
        return findPosition(result,status,x,y,n,pos,number);

    }
}

60. 第k个排列

给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。

按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:

“123”
“132”
“213”
“231”
“312”
“321”
给定 n 和 k,返回第 k 个排列。

说明:

给定 n 的范围是 [1, 9]。
给定 k 的范围是[1, n!]。
示例 1:

输入: n = 3, k = 3
输出: “213”
示例 2:

输入: n = 4, k = 9
输出: “2314”

class Solution {
        public String getPermutation(int n, int k) {
        k = k-1;
        int divided = 0;
        int mul = 0;
        List<Integer> list = new ArrayList<>();
        for(int i = 1; i<=n;i++){
            list.add(i);
        }
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = n - 1; i >= 1; i--) {
            mul = NMul(i);
            divided = k / mul;
            k = k % mul;
            stringBuilder.append(list.get(divided));
            list.remove(divided);
        }
        stringBuilder.append(list.get(0));
        return stringBuilder.toString();
    }

    private int NMul(int n) {
        int val = 1;
        for (int i = n; i >= 1; i--) {
            val *= i;
        }
        return val;
    }
}

61.旋转列表

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

示例 1:

输入: 1->2->3->4->5->NULL, k = 2
输出: 4->5->1->2->3->NULL
解释:
向右旋转 1 步: 5->1->2->3->4->NULL
向右旋转 2 步: 4->5->1->2->3->NULL
示例 2:

输入: 0->1->2->NULL, k = 4
输出: 2->0->1->NULL
解释:
向右旋转 1 步: 2->0->1->NULL
向右旋转 2 步: 1->2->0->NULL
向右旋转 3 步: 0->1->2->NULL
向右旋转 4 步: 2->0->1->NULL

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode rotateRight(ListNode head, int k) {
        if(head == null){
            return head;
        }
        ListNode pHead = head;
        int size = 1;
        while(pHead.next != null){
            size++;
            pHead = pHead.next;
        }
       
        pHead.next = head;
        k = size-(k%size);
        for(int i = 0; i < k ; i++){
            head = head.next;
        }
        pHead = head;
        while(pHead.next != head){
            pHead = pHead.next;
        }
        pHead.next = null;
        return head;
    }
}

62. 不同路径

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。

问总共有多少条不同的路径?

例如,上图是一个7 x 3 的网格。有多少可能的路径?

说明:m 和 n 的值均不超过 100。

示例 1:

输入: m = 3, n = 2
输出: 3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。

  1. 向右 -> 向右 -> 向下
  2. 向右 -> 向下 -> 向右
  3. 向下 -> 向右 -> 向右
    示例 2:

输入: m = 7, n = 3
输出: 28

class Solution {
    public int uniquePaths(int m, int n) {
        int[][] dp = new int[m+1][n+1];
        dp[1][1] = 1;
        for(int i = 1;i < m+1;i++) {
            for(int j = 1;j < n+1;j++) {
                if(i == 1 && j == 1) continue;
                dp[i][j] = dp[i-1][j] + dp[i][j-1];
            }
        }
        return dp[m][n];
    }
   
}

63. 不同路径 II

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。

现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?

网格中的障碍物和空位置分别用 1 和 0 来表示。

说明:m 和 n 的值均不超过 100。

示例 1:

输入:
[
[0,0,0],
[0,1,0],
[0,0,0]
]
输出: 2
解释:
3x3 网格的正中间有一个障碍物。
从左上角到右下角一共有 2 条不同的路径:

  1. 向右 -> 向右 -> 向下 -> 向下
  2. 向下 -> 向下 -> 向右 -> 向右
class Solution {
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        int m = obstacleGrid.length;
        if(m <= 0){
            return 0;
        }
        int n = obstacleGrid[0].length;
        int[][] dp = new int[m+1][n+1];
        dp[1][1] = 1;
        for(int i = 1;i < m+1;i++) {
            for(int j = 1;j < n+1;j++) {
                if(obstacleGrid[i-1][j-1]==1){
                    dp[i][j] = 0;
                }else if(i == 1 && j == 1){
                    continue;
                }else{
                    dp[i][j] = dp[i-1][j] + dp[i][j-1];
                }               
            }
        }
        return dp[m][n];
    
    }
}

64. 最小路径和

给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。

说明:每次只能向下或者向右移动一步。

示例:

输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。

class Solution {
    public int minPathSum(int[][] grid) {
        int m = grid.length;
        if(m <= 0){
            return 0;
        }
        int n = grid[0].length;
        int[][] dp = new int[m+1][n+1];
        for(int i = 0; i < m+1; i++){
            dp[i][0] = Integer.MAX_VALUE;
        }
        for(int i = 0; i < n+1; i++){
            dp[0][i] = Integer.MAX_VALUE;
        }
        
        for(int i = 1;i < m+1;i++) {
            for(int j = 1;j < n+1;j++) {
                 if(i == 1 && j == 1){
                    dp[1][1] = grid[0][0];
                }else{
                    dp[i][j] = Math.min(dp[i-1][j],dp[i][j-1])+ grid[i-1][j-1];
                }               
            }
        }
        return dp[m][n];
    }
}

66. 加一

给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。

最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。

你可以假设除了整数 0 之外,这个整数不会以零开头。

示例 1:

输入: [1,2,3]
输出: [1,2,4]
解释: 输入数组表示数字 123。
示例 2:

输入: [4,3,2,1]
输出: [4,3,2,2]
解释: 输入数组表示数字 4321。

class Solution {
    public int[] plusOne(int[] digits) {
        int size = digits.length;
        int number = 0;
        boolean find = false;
        while(!find && size >= 1){
            number = digits[size -1]+1;
            if(number < 10){
                find = true;
            }
            digits[size -1] = number % 10;
            size--;
        }
        if(!find){
            int[] newDigits = new int[digits.length+1];
            newDigits[0] = 1;
            for(int i = 0; i< digits.length;i++){
                newDigits[i+1] = digits[i];
            }
            return newDigits;
        }
        return digits;
    }
}

67. 二进制求和

给定两个二进制字符串,返回他们的和(用二进制表示)。

输入为非空字符串且只包含数字 1 和 0。

示例 1:

输入: a = “11”, b = “1”
输出: “100”
示例 2:

输入: a = “1010”, b = “1011”
输出: “10101”

class Solution {
    public String addBinary(String a, String b) {
        int aSize = a.length()-1;
        int bSize = b.length()-1;
        List<Integer> list = new LinkedList<>();
        int position = 0;
        int value = 0;
        int addValue = 0;
        while(position <= aSize || position <= bSize){
            int ca = position > aSize?0:a.charAt(aSize-position)-'0';
            int cb = position > bSize?0:b.charAt(bSize-position)-'0';
            value = addValue+ca+cb;
            if(value/2 == 1){
                addValue = 1;
                value = value%2;
            }else{
                addValue = 0;
            }
            list.add(0,value);   
            value = 0;
            position++;
        }
        if(addValue == 1){
            list.add(0,1);
        }    
        if(list.size()==0){
            return "0";
        }
        StringBuilder str = new StringBuilder();
        for(int i = 0;i<list.size();i++){
            str.append(list.get(i));
        }
        
        return str.toString();
    }
}

69.x的平方根

实现 int sqrt(int x) 函数。

计算并返回 x 的平方根,其中 x 是非负整数。

由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。

示例 1:

输入: 4
输出: 2
示例 2:

输入: 8
输出: 2
说明: 8 的平方根是 2.82842…,
由于返回类型是整数,小数部分将被舍去。

class Solution {
    public int mySqrt(int x) {
        return compare(0,x,x);
    }
    public int compare(int before, int end, int target){
        if(before == end){
            return before;
        }
        if(end - before == 1){
            if(end*end == target){
                return end;
            }
            return before;
        }
        int harf = (end-before)/2 +before;
        if(harf == target/harf){
            return harf;
        }
        if(harf > target/harf){
            end = harf;
        }else{
            before = harf;
        }
        return compare(before,end,target);
        
    }
}

70. 爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。

示例 1:

输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。

  1. 1 阶 + 1 阶
  2. 2 阶
    示例 2:

输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。

  1. 1 阶 + 1 阶 + 1 阶
  2. 1 阶 + 2 阶
  3. 2 阶 + 1 阶
class Solution {
    public int climbStairs(int n) {
        if( n == 0 || n == 1){
            return 1;
        }
        int[] result = new int[n+1];
        result[0] = 1;
        result[1] = 1;
        for(int i = 2; i < n+1; i++){
            result[i] = result[i-1] + result[i-2];
        }
        return result[n];
    }
}

72. 编辑距离

给定两个单词 word1 和 word2,计算出将 word1 转换成 word2 所使用的最少操作数 。

你可以对一个单词进行如下三种操作:

插入一个字符
删除一个字符
替换一个字符
示例 1:

输入: word1 = “horse”, word2 = “ros”
输出: 3
解释:
horse -> rorse (将 ‘h’ 替换为 ‘r’)
rorse -> rose (删除 ‘r’)
rose -> ros (删除 ‘e’)
示例 2:

输入: word1 = “intention”, word2 = “execution”
输出: 5
解释:
intention -> inention (删除 ‘t’)
inention -> enention (将 ‘i’ 替换为 ‘e’)
enention -> exention (将 ‘n’ 替换为 ‘x’)
exention -> exection (将 ‘n’ 替换为 ‘c’)
exection -> execution (插入 ‘u’)

class Solution {
    public int minDistance(String word1, String word2) {
        if(word1.length() == 0 || word2.length() == 0){
            return Math.abs(word1.length()-word2.length());
        }
        int[][] result = new int[word1.length()+1][word2.length()+1];
        
        for(int i = 0; i <= word2.length();i++){
            result[0][i] = i;
        }
        for(int i = 0; i <= word1.length();i++){
            result[i][0] = i;
        }
        if(word1.charAt(0) == word2.charAt(0)){
            result[1][1] = 0;
        }else{
            result[1][1] = 1;
        }

        char s1;
        char s2;
        int min = 0;
        for(int i = 1; i <= word1.length(); i++){
            s1 = word1.charAt(i-1);
            for(int j = 1; j <= word2.length(); j++){
                if(i==1 && j==1) continue;
                s2 = word2.charAt(j-1);
                if(s1 == s2){
                    result[i][j] = result[i-1][j-1];
                }else{
                    min = Math.min(result[i-1][j-1],result[i][j-1]);
                    result[i][j] = 1+Math.min(min,result[i-1][j]);
                }

            }
        }
        
        return result[word1.length()][word2.length()];
        
    }
}

73. 矩阵置零

给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0。请使用原地算法。

示例 1:

输入:
[
[1,1,1],
[1,0,1],
[1,1,1]
]
输出:
[
[1,0,1],
[0,0,0],
[1,0,1]
]
示例 2:

输入:
[
[0,1,2,0],
[3,4,5,2],
[1,3,1,5]
]
输出:
[
[0,0,0,0],
[0,4,5,0],
[0,3,1,0]
]
进阶:

一个直接的解决方案是使用 O(mn) 的额外空间,但这并不是一个好的解决方案。
一个简单的改进方案是使用 O(m + n) 的额外空间,但这仍然不是最好的解决方案。
你能想出一个常数空间的解决方案吗?

class Solution {
    public void setZeroes(int[][] matrix) {
        int row = matrix.length;
        if(row == 0){
            return;
        }
        int column = matrix[0].length;
        int[] columns = new int[column];
        boolean isZero = false;
        boolean containsZero = false;
        for(int i = 0; i<row;i++){
            for(int j = 0 ; j < column; j++){
                if(isZero){
                    matrix[i-1][j] = 0;
                }
                if(matrix[i][j] == 0){
                    columns[j] = 1;
                    containsZero = true;
                }
            }
            if(containsZero){
                isZero = true;
            }else{
                isZero = false;
            }
            containsZero = false;
        }
        if(isZero){
            for(int j = 0 ; j < column; j++){
                matrix[row-1][j] = 0;
            }
        }
        for(int i = 0; i < column; i++){
            if(columns[i]==1){
                for(int j = 0; j < row; j ++){
                     matrix[j][i] = 0;
                }
            }
            
        }
    }
}

74. 搜索二维矩阵

编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:

每行中的整数从左到右按升序排列。
每行的第一个整数大于前一行的最后一个整数。
示例 1:

输入:
matrix = [
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
target = 3
输出: true
示例 2:

输入:
matrix = [
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
target = 13
输出: false

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        int row = matrix.length;
        if(row == 0){
            return false;
        }
        int column = matrix[0].length;
        if(column == 0){
            return false;
        }
        return search(matrix,target,0,0,row - 1,column - 1);
    }
    public boolean find(int[][] matrix, int target,int beforeX,int beforeY,int endX, int endY){
        if(beforeX >= endX - 1 || beforeY >= endY - 1){
            search(matrix,target,beforeX,beforeY,endX,endY);

        }
        int harfX = ( beforeX + endX ) / 2;
        int harfY = ( beforeY + endY) / 2;
        if(matrix[harfX][harfY] == target){
            return true;
        }
        if(matrix[harfX][harfY] < target){
            return find(matrix,target,harfX,harfY,endX,endY);
        }
        return find(matrix,target,beforeX,beforeY,harfX,harfY);
    }
    public boolean search(int[][] matrix, int target,int beforeX,int beforeY,int endX, int endY){
        int row = matrix.length;
        int column = matrix[0].length;
        int positionX = beforeX;
        int positionY = beforeY;
        
        while(!((positionX == endX && positionY > endY) || positionX > endX)){
            if(matrix[positionX][positionY] == target){
                return true;
            }
            positionY ++;
            if(positionY == column){
                positionY = 0;
                positionX++;
            }
        }
        return false;
    }
}

75. 颜色分类

给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

注意:
不能使用代码库中的排序函数来解决这道题。

示例:

输入: [2,0,2,1,1,0]
输出: [0,0,1,1,2,2]
进阶:

一个直观的解决方案是使用计数排序的两趟扫描算法。
首先,迭代计算出0、1 和 2 元素的个数,然后按照0、1、2的排序,重写当前数组。
你能想出一个仅使用常数空间的一趟扫描算法吗?

class Solution {
    public void sortColors(int[] nums) {
        int before = 0;
        int end = nums.length - 1;
        if(end <= 0){
            return;
        }      
        find(nums,before,end,1,nums[0]);
    }

    public void find(int[] nums,int before,int end,int positionBefore ,int val){
        if(val == 0){
            val = positionBefore<nums.length?nums[positionBefore]:-1;
            nums[before] = 0;
            before ++;
            positionBefore++;
        }else if(val == 2){
            val = nums[end];
            nums[end] = 2;
            end --;
        }else {
            val = positionBefore<nums.length?nums[positionBefore]:-1;
            positionBefore++;
        }
        if(positionBefore > end + 1){
            for(int i = before;i <= end; i++){
                nums[i] = 1;
            }
            return;
        }
        find(nums,before,end,positionBefore,val);

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值