算法刷题记录(LeetCode 31-60)

32. Longest Valid Parentheses

Leetcode:Leetcode
解法非常有意思,使用了一个常置元素

    public int longestValidParentheses(String s) {
        Stack<Integer> indexStack=new Stack<>() ;
        int maxParenthesis=0;
        indexStack.push(-1);
        for(int i=0;i<s.length();i++){
            if(s.charAt(i)=='('){
                indexStack.push(i);
            }
            else{
                indexStack.pop();
                if(!indexStack.isEmpty()){
                    maxParenthesis=Math.max(maxParenthesis,i-indexStack.peek());
                }
                else{
                    indexStack.push(i);
                }
            }
        }
        return maxParenthesis;
    }

33.Search an element in a sorted and rotated Array

class Solution {
    public int search(int[] nums, int target) {
        return search2(nums,0,nums.length-1,target);
        
    }
    public int search2(int[] nums,int left,int right,int target){
        int pivot = findPivot(nums,left,right);
        if (pivot==-1){
           return binarySearch(nums,left,right,target);
        }
        if (target==nums[pivot]){
            return pivot;
        }

        if(nums[0]<=target){
           return binarySearch(nums,left,pivot-1,target);
        }
        return binarySearch(nums,pivot+1,right,target);

    }
    public int findPivot(int[] nums,int left,int right){
        if(left>right){
            return -1;
        }
        if(left==right){
            return left;
        }
        var mid= (right+left)/2;
        if (nums[mid]>nums[mid+1]){
            return mid;
        }
        if(mid>left&&nums[mid]<nums[mid-1]){
            return mid-1;
        }
        if(nums[left]>=nums[mid]){
            return findPivot(nums,left,mid-1);
        }
            return findPivot(nums,mid+1,right);
    }
    int binarySearch(int arr[], int low, int high, int key)
    {
    if (high < low)
        return -1;
 
    int mid = (low + high) / 2;
    if (key == arr[mid])
        return mid;
 
    if (key > arr[mid])
        return binarySearch(arr, (mid + 1), high, key);
 
    return binarySearch(arr, low, (mid - 1), key);
    }
}

34. Find First and Last Position of Element in Sorted Array

    public int[] searchRange(int[] nums, int target) {
        if(nums==null||nums.length==0){
            return new int[]{-1,-1};
        }
        int left=0;
        int right=nums.length-1;
        int mid=0;
        while(left<=right){
            mid=(left+right)>>1;
            if(nums[mid]==target){
                break;
            }
            else if(target<nums[mid]){
                right=mid-1;
            }
            else{
                left=mid+1;
            }
        }
        if(nums[mid]!=target){
            return new int[]{-1,-1};
        }
        else{
            int l_idx=mid;
            int r_idx=mid;
            while(l_idx>=0&&nums[l_idx]==target){
                l_idx--;
            }
            while(r_idx<nums.length&&nums[r_idx]==target){
                r_idx++;
            }
            return new int[]{l_idx+1,r_idx-1};

        }

    }

*35. Search Insert Position

    int searchInsert(vector<int>& nums, int target) {
        int left=0;
        int right=nums.size()-1;
        while (left<right){
            int mid=(left+right)>>1;
            if (nums[mid]<target){
                left=mid+1;
            }
            else{
                right=mid;
            }
        }
        return nums[left]>=target? left:left+1;
    }

36. Valid Sudoku

    public boolean isValidSudoku(char[][] board) {
        int[][] horizontal=new int[9][9+1];
        int[][] vertical=new int[9][9+1];
        int[][][] nine_blocks=new int[3][3][9+1];
        for (int i=0;i<9;i++){
            for (int j=0;j<9;j++){
                if(!Character.isDigit(board[i][j])){
                    continue;
                }
                int val=board[i][j]-'0';
                horizontal[i][val]++;
                vertical[j][val]++;
                nine_blocks[i/3][j/3][val]++;
                if (horizontal[i][val]>1||vertical[j][val]>1||nine_blocks[i/3][j/3][val]>1){
                    return false;
                }
            }
        }
        return true;
    }

38. Count and Say

    public String countAndSay(int n) {
        String[] dp=new String[n+1];
        dp[1]="1";
        StringBuilder builder=new StringBuilder();
        for (int i=2;i<=n;i++){
            builder.setLength(0);
            String prev_str=dp[i-1];
            char prev=dp[i-1].charAt(0);
            int count=0;
            for(int j=0;j<prev_str.length();j++){
                if (prev==prev_str.charAt(j)){
                    count++;
                }
                else{
                    builder.append(count);
                    builder.append(prev);
                    prev=prev_str.charAt(j);
                    count=1;
                }
            }
            builder.append(count);
            builder.append(prev);
            dp[i]=builder.toString();
        }
        return dp[n];
    }

39. Combination Sum

class Solution {
    public static List<List<Integer>> res= new ArrayList<>();
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        res.clear();
        bfs(0,0,target,candidates,new ArrayList<Integer>());
        return res;


    }
    public void bfs(int i,int currSum,int target,int[] candidates,ArrayList<Integer> currElements){
        if(target==currSum){
            res.add((ArrayList<Integer>) currElements.clone());
            return;
        }
        if(currSum>target){
            return;
        }
        if(i>=candidates.length){
            return;
        }
        currElements.add(candidates[i]);
        bfs(i,currSum+candidates[i],target,candidates,currElements);
        currElements.remove(currElements.size()-1);
        bfs(i+1,currSum,target,candidates,currElements);
    }
}

40. Combination Sum II

    public static List<List<Integer>> res= new ArrayList<>();
    public static int prev=-1;
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        res.clear();
        prev=-1;
        Arrays.sort(candidates);
        backTrack(new ArrayList<>(),candidates,0,target);
        return res;
    }
    public void backTrack(ArrayList<Integer> curr,int[] candidates, int begin,int target){
        if(target==0){
            res.add((List<Integer>) curr.clone());
            return;
        }
        if(target<0){
            return;
        }
        for(int i=begin;i<candidates.length;i++){
            if(prev==candidates[i]){
                continue;
            }
            curr.add(candidates[i]);
            backTrack(curr,candidates,i+1,target-candidates[i]);
            curr.remove(curr.size()-1);
            prev=candidates[i];
        }
    }

41. (HARD) First Missing Positive

核心思路 用本数组建立哈希表

    public int firstMissingPositive(int[] nums) {
        int idx_value;
        for(int i=0;i<nums.length;i++){
            nums[i]=nums[i]>0?nums[i]:0;
        }
        for(int i=0;i<nums.length;i++){
            int val=Math.abs(nums[i]);
            if(1<=val && val<=nums.length){
                idx_value=nums[val-1];
                if(idx_value>0){
                    nums[val-1]=-1*idx_value;
                }
                else if(idx_value==0){
                    nums[val-1]=-1*(nums.length+1);
                }
            }
        }
        for(int i=1;i<=nums.length;i++){
            if(nums[i-1]>=0){
                return i;
            }
        }
        // Arrays.stream(nums).forEach(System.out::print);
        return nums.length+1;

    }

42. Trapping Rain Water

youtube

43. Multiply Strings(Solved)

不难 但恶心

    public String multiply(String num1, String num2) {
        if (num1.charAt(0) == '0' || num2.charAt(0) == '0') {
            return "0";
        }
        char[] res = new char[num1.length() + num2.length()];
        Arrays.fill(res,'0');
        int sum_Carrying=0;
        for (int i = 0; i < num1.length(); i++) {
            char[] levelRes = new char[num2.length() + 1];
            int carrying = 0;
            Arrays.fill(levelRes, '0');
            if (num1.charAt(i) == '0') {
                continue;
            }
            for (int j = num2.length()-1; j >=0; j--) {
                int product = Character.getNumericValue(num1.charAt(i)) * Character.getNumericValue(num2.charAt(j)) + carrying;
                int digit = product % 10;
                carrying = product / 10;
                levelRes[j+1]= (char) (digit+'0');
            }
            levelRes[0]= (char) (carrying+'0');
            for (int k = levelRes.length-1; k >=0; k--) {
                int curr_sum=res[k+i]-'0'+levelRes[k]-'0'+sum_Carrying;
                res[k+i]= (char) (curr_sum%10+'0');
                sum_Carrying=curr_sum/10;
            }
            if(sum_Carrying!=0){
                for(int m=i-1;m>=0;m--){
                    int curr_sum=res[m]-'0'+sum_Carrying;
                    res[m]= (char) (curr_sum%10+'0');
                    sum_Carrying=curr_sum/10;
                    if(sum_Carrying==0){
                        break;
                    }
                }
            }

        }
        for(var ch:res){
            System.out.println(ch);
        };
        return new String(res).replaceAll("^0*","");
    }

44. Wildcard Matching

dp

我们来看这样一个表

其中,横轴为string s,纵轴为pattern p
这个表第(m,n)个格子的意义是:【p从0位置到m位置】这一整段,是否能与【s从0位置到n位置】这一整段匹配
也就是说,如果表格的下面这一个位置储存的是T(True):
说明,"adcb"和"a*b"这一段是可以匹配的,你不用管前面发生了什么,你只要知道,这两段是匹配的,这就是动态规划为什么很棒棒


好,我们回到最初的起点。那么我们如何在这个表格上愉快地行走呢?
我在(START,START)这个位置放了一个T,这就是我们开始行走的位置
只有在T时才能继续往下走

那么从T可以往哪个方向走?
这道题是一个字符串匹配题,那字符串匹配肯定是不能回头的,你不可能在"abcde"里面倒着走,比如从e走到d
这个“不能倒着走”的规定,反映到我们的表格当中,就是只能往右下角走,大家可以细品一下为什么
(往右走、往下走也是有可能的,待会儿我们再说;反正左、上、左上角是不可能的,因为不能倒着走!)
往右下角走,我来举个例子,比如从刚才的初始位置出发,往右下角走一格,来到(a,a)这个位置,发现新引入的这两个字母正好匹配,于是我们在这里记录一个“T”。

就是这么简单,如果p和s里只有字母,没有"“和”?“这两个东西,每次你只要从原来T的某个格子往右下角走一格,如果新引入的两个字母正好匹配,你就可以在新的格子里记录一个T。
再敲一次黑板:只能从T的格子走,如果某个格子里没有东西(即False),你是不可以从那里出发的。

下面我们来介绍”
“和”?"
我为什么在标题里称这个表格为一个棋盘,是因为我觉得这像是一个下棋游戏
我们知道,中国象棋里每个棋子的功能都不同,像小兵每次只能直走一格,但车却可以直走任意格,还有的棋子则能跳着走
我们这里,普通字母如a、b就像是小兵角色,遇到他们只能右下走一格,走完这一步后判断新引入两个字母是否匹配才能记录T;
而"*“和”?“则是有特殊技能的角色!
角色:"*"
特技:铲平道路
描述:如果这一行是"*",可以从上一行的任意T出发,向下、右铲平这一行的任意道路
示例:

所到之处,皆为平地
"*"可以从原来T向正下方走的原因:星号可以匹配空串
"*"可以铲平所有右边道路的原因:星号可以匹配任意长度字符串
大家可以品一品这两个原因。

在讲解另一个狠角色”?“之前,我们再往下走两步,巩固一下之前的知识。
接下来我们在pattern里遇到了一个b,它是一个普通字母,所以只能从上一行某个T往右下角走到达,而且字母匹配才能记录T,于是我们发现可以走这两步:

角色:”?"
特技:狸猫换太子
描述:如果这一行是"?“,从上一行某个T也只能向右下角走,但不必匹配字母就能记录T
示例:

只要有T就可以直接往右下角走一格,不用在意字母。这里太子“e”被狸猫”?"抵消了

wow,一下子来到了最后一格,小兵走一格就可以liao


要判定是否成功匹配,只要看一个格子!!如果最最右下角的格子是T,那就是匹配成功了,不用在意之前到底发生了什么
所以我们成功了,撒花✿✿ヽ()ノ✿

    public boolean isMatch(String s, String p) {
        boolean[][] dp=new boolean[p.length()+1][s.length()+1];
        dp[0][0]=true;
        if (s.isEmpty()&&p.matches("^\\**$")){
            return true;
        }
        for (int i=1;i<=p.length();i++){
            for (int j=1;j<=s.length();j++){
                if (p.charAt(i-1)=='*'){
                    if (dp[i-1][0]){
                        Arrays.fill(dp[i],true);
                    }
                    if (dp[i - 1][j]){
                        for (int k=j;k<=s.length();k++){
                            dp[i][k]=true;
                        }
                        break;
                    }
                }
                else if (dp[i-1][j-1]&&(p.charAt(i-1)=='?'||p.charAt(i-1)==s.charAt(j-1))){
                    dp[i][j]=true;
                }
            }
        }
        return dp[p.length()][s.length()];
    }

O ( n ) O(n) O(n)解法

45. Jump Game II

DP

class Solution {
    public static int DIS_REACHABLE=50000;
    public int jump(int[] nums) {
        int[] dp=new int[nums.length];
        Arrays.fill(dp,DIS_REACHABLE);
        dp[nums.length-1]=0;
        for (int i=nums.length-2;i>=0;i--){
            for (int j=1;j<=nums[i]&&j+i<nums.length;j++){
                dp[i]=Math.min(dp[i],dp[i+j]+1);
            }
        }
        return dp[0];
    }
}

Sliding Window

    public int jump(int[] nums) {
        int res=0;
        int left=0,right=1;

        while (right<nums.length){
            int currLength=0;
            res++;
            while (left<right){
                currLength=Math.max(left+nums[left],currLength);
                left++;
            }
            left=right;
            right=currLength+1;
        }
        return res;
    }

46. Permutations

class Solution {
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> res=new ArrayList<>();
        subPermute(nums,res,0,nums.length-1);
        return res;
    }
    public void subPermute(int[] nums,List<List<Integer>> res,int left,int right){
        if (right==left){
            res.add(Arrays.stream(nums).boxed().collect(Collectors.toList()));
            return;
        }
        if(right>left){
            for(int i=left;i<=right;i++){
                swap(nums, left,i );
                subPermute(nums,res,left+1,right);
                swap(nums,left,i);
            }
        }
        
    }
    public void swap(int[] arr,int a,int b){
        int temp= arr[a];
        arr[a] = arr[b];
        arr[b] = temp;
    }
    
}

47. Permutations II

class Solution {
    public static HashSet<List<Integer>> res=new HashSet<>();

    public List<List<Integer>> permuteUnique(int[] nums) {
        res.clear();
        int i = 0;
        backTrack(nums,0,nums.length-1);
        return res.stream().toList();
    }

    public void backTrack(int[] nums,int left,int right) {
        if (left==right){
            res.add(Arrays.stream(nums).boxed().toList());
        }
        else if(left<right){
            for(int i=left;i<=right;i++){
                if(left!=i&&nums[left]==nums[i]){
                    continue;
                }
                swap(nums,left,i);
                backTrack(nums,left+1,right);
                swap(nums, left,i);
            }
        }
    }

    public void swap(int[] arr, int a, int b) {
        int temp = arr[a];
        arr[a] = arr[b];
        arr[b] = temp;
    }

}

Intersection of Two Linked Lists

使用HaseSet,空间复杂度 O ( m ) O(m) O(m)

    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        HashSet<ListNode> storaged=new HashSet<>();
        ListNode curr_A=headA;
        ListNode curr_B=headB;
        while(curr_A!=null){
            storaged.add(curr_A);
            curr_A=curr_A.next;
        }
        while(curr_B!=null){
            System.out.println(curr_B.val);
            if(storaged.contains(curr_B)){
                return curr_B;
            }
            curr_B=curr_B.next;
        }
        return null;
    }

空间复杂度 O ( 1 ) O(1) O(1)

    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode curr_A=headA;
        ListNode curr_B=headB;
        while(curr_A!=curr_B){
            curr_A=curr_A==null?headB:curr_A.next;
            curr_B=curr_B==null?headA:curr_B.next;
        }
        return curr_A;
    }

48. Rotate Image

    public void rotate(int[][] matrix) {
        int left=0;
        int right=matrix.length-1;
        int top;
        int bottom;
        while(left<right){
            for(int i=0;i<right-left;i++){
                top=left;
                bottom=right;
                int topLeft=matrix[top][left+i];
                matrix[top][left+i]=matrix[bottom-i][left];
                matrix[bottom-i][left]=matrix[bottom][right-i];
                matrix[bottom][right-i]=matrix[top+i][right];
                matrix[top+i][right]=topLeft;
            }
            left++;
            right--;
        }
    }

49. Group Anagrams

    public List<List<String>> groupAnagrams(String[] strs) {
        HashMap<String,List<String>> dict=new HashMap<>();
        for (String s:strs){
            int[] counts=new int[26];
            for (int i=0;i<s.length();i++){
                counts[s.charAt(i)-'a']++;
            }
            if (!dict.containsKey(Arrays.toString(counts))){
                dict.put(Arrays.toString(counts),new ArrayList<>());
                dict.get(Arrays.toString(counts)).add(s);
            }
            else{
                dict.get(Arrays.toString(counts)).add(s);
            }
        }
        return dict.values().stream().toList();
    }

51. N-Queens

class Solution {
    public static List<List<String>> res=new ArrayList<>();
    public static HashSet<Integer> negDiag=new HashSet<>();
    public static HashSet<Integer> posDiag=new HashSet<>();
    public static HashSet<Integer> col=new HashSet<>();
    public List<List<String>> solveNQueens(int n) {
        res.clear();
        negDiag.clear();
        posDiag.clear();
        col.clear();
        char[][] board=new char[n][n];
        Arrays.stream(board).forEach(a->Arrays.fill(a,'.'));
        backTrack(board,0,n);
        return res;
    }
    public void backTrack(char[][] board,int row,int n){
        if (row==n){
            String[] copy=new String[n];
            for(int i=0;i<n;i++){
                copy[i]=new String(board[i]);
            }
            res.add(Arrays.asList(copy));
            return;
        }
        for(int c=0;c<n;c++){
            if (col.contains(c)||posDiag.contains(row+c)||negDiag.contains(row-c)){
                continue;
            }
            col.add(c);
            posDiag.add(row+c);
            negDiag.add(row-c);
            board[row][c]='Q';
            backTrack(board,row+1,n);
            col.remove(c);
            posDiag.remove(row+c);
            negDiag.remove(row-c);
            board[row][c]='.';
    }
}
}

55. Jump Game

dp O ( n 2 ) O(n^2) O(n2)

    public boolean canJump(int[] nums) {
        boolean[] available=new boolean[nums.length];
        available[nums.length-1]=true;
        for(int i=nums.length-2;i>=0;i--){
            for(int j=1;j<=nums[i]&&i+j<nums.length;j++){
                if(available[i+j]){
                    available[i]=true;
                    break;
                }
            }
        }
        return available[0];
    }

gready O ( n ) O(n) O(n)

56. Merge Intervals

youtube

  public int[][] merge(int[][] intervals) {
        int len=intervals.length;
        Arrays.sort(intervals,(i,j)->
            i[0]-j[0]
        );
        Stack<Integer[]> res_stack=new Stack<Integer[]>();
        Integer[] tmp = Arrays.stream(intervals[0]).boxed().toArray( Integer[]::new );
        res_stack.push(tmp);
        for(int i=1;i<len;i++){
            int start=intervals[i][0];
            int end=intervals[i][1];
            Integer[] curr_biggest=res_stack.peek();
            int biggest_end=res_stack.peek()[1];
            if(biggest_end<start){
                Integer[] newArray = Arrays.stream(intervals[i]).boxed().toArray( Integer[]::new );
                res_stack.push(newArray);
            }
            else if(end>biggest_end){
                curr_biggest[1]=end;
                res_stack.pop();
                res_stack.push(curr_biggest);
            }
        }
        int res_len=res_stack.size();
        int[][] res=new int[res_len][2];
        for(int j=0;j<res_stack.size();j++){
            int[] res_int = Arrays.stream(res_stack.get(j)).mapToInt(Integer::intValue).toArray();
            res[j]=res_int;
        }
        return res;
    }

58. Length of Last Word(Solved?)

import java.util.regex.Matcher;
import java.util.regex.Pattern;
class Solution {
    public int lengthOfLastWord(String s) {
        String regex="\\w+\\s*$";
        Pattern pattern=Pattern.compile(regex);
        Matcher matcher=pattern.matcher(s);
        if(matcher.find()){
            System.out.println("found");
            return matcher.group().strip().length();
        }
        return 0;
    }
}

59. Spiral Matrix II(Solved?)

    public int[][] generateMatrix(int n) {
        int top =0;
        int left=0;
        int right=n-1;
        int bottom=n-1;
        int curr=1;
        int[][] res=new int[n][n];
        while(top<=bottom||left<=right){
            //top left -> right
            for(int i=left;i<right;i++){
                res[top][i]=curr;
                curr++;
            }
            for(int j=top;j<bottom;j++){
                res[j][right]=curr;
                curr++;
            }
            //bottom right -> left
            for(int i=right;i>left;i--){
                res[bottom][i]=curr;
                curr++;
            }
            for(int j=bottom;j>top;j--){
                res[j][left]=curr;
                curr++;
            }
            top++;
            bottom--;
            left++;
            right--;
        }
        if(n%2!=0){
            res[n/2][n/2]=curr;
        }
        return res;
    }

60. Permutation Sequence

class Solution {
    public String getPermutation(int n, int k) {
        k--;
        int[] dp = new int[n + 1];
        dp[1] = 1;
        for (int i = 2; i <= n; i++) {
            dp[i] = (i-1) * dp[i - 1];
        }
        int[] valid = new int[n + 1];
        Arrays.fill(valid, 1);
        StringBuilder res = new StringBuilder();
        for (int i = n; i >= 1; i--) {
            int order = k / dp[i]+1;
            for (int j = 1; j <= n; j++) {
                order -= valid[j];
                if (order == 0) {
                    res.append(j);
                    valid[j]=0;
                    break;
                }
            }
            k %= dp[i];
        }
        for (int j=1;j<=n;j++){
            if (valid[j]!=0){
                res.append(valid[j]);
            }
        }
        return res.toString();
    }
}

66. Plus One

    public int[] plusOne(int[] digits) {
        digits[digits.length-1]++;
        ArrayList<Integer> res = new ArrayList<>();
        int carry = 0;
        for (int i = digits.length - 1; i >= 0; i--) {
            int val=digits[i]+carry;
            res.add(val%10);
            carry=val/10;
        }
        if (carry>0){
            res.add(1);
        }
        int[] res_arr=new int[res.size()];
        for (int i=0;i<res_arr.length;i++){
            res_arr[i]=res.get(res.size()-i-1);
        }
        return res_arr;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值