【leetcode刷题笔记(8)】

(1)9. 回文数

思路1:负数一定为false,小于10的正数一定为true,个位为0的数一定为false,然后将数字转化为string进行判断。

class Solution {
    public boolean isPalindrome(int x) {
        if(x < 0){
            return false;
        }
        if(x < 10){
            return true;
        }
        if(x % 10 == 0){
            return false;
        }
        String str = String.valueOf(x);
        return strPalidrome(str);  

    }
    public boolean strPalidrome(String str){
        if(str.length() <= 1){
            return true;
        }
        if(str.charAt(0) == str.charAt(str.length()-1)){
            if(str.length()==2){
                return true;
            }else{
                return strPalidrome(str.substring(1,str.length()-1));
            }
        }
        return false;
    }
}

思路2:获得x的逆序数字,判断是否与x相等。

class Solution {
    public boolean isPalindrome(int x) {
        if(x < 0){
            return false;
        }
        int temp = 0;
        int y = 0;
        int num = x;
        while(num > 0){
            temp = num % 10;
            y = y * 10 + temp;
            num = num / 10;
        }
        return x == y;

    }
}

(2)29. 两数相除

思路:使用位运算。

class Solution {
    public int divide(int dividend, int divisor) {
        if (dividend == 0) {
            return 0;
        }
        if (dividend == Integer.MIN_VALUE && divisor == -1) {
            return Integer.MAX_VALUE;
        }
        boolean negative;
        negative = (dividend ^ divisor) <0;//用异或来计算是否符号相异
        long t = Math.abs((long) dividend);
        long d= Math.abs((long) divisor);
        int result = 0;
        for (int i=31; i>=0;i--) {
            if ((t>>i)>=d) {//找出足够大的数2^n*divisor
                result+=1<<i;//将结果加上2^n
                t-=d<<i;//将被除数减去2^n*divisor
            }
        }
        return negative ? -result : result;//符号相异取反
    }
}

(3)46. 全排列(错1)

题解思路:动态规划,使用一个数组存储是否遍历到该数字。

class Solution {
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        int[] visited = new int[nums.length];
        
        childPermute(res, nums,new ArrayList<Integer>(),visited);
        return res;
    }
    public void childPermute(List<List<Integer>> res,int[] nums, List<Integer> temp, int[] visited){
        if(temp.size() == nums.length){
            res.add(new ArrayList<>(temp));
            return;
        }
        for(int i = 0; i < nums.length; i++){
            if(visited[i] == 1){
                continue;
            }else{
                visited[i] = 1;
                temp.add(nums[i]);

                childPermute(res, nums, temp, visited);

                visited[i] = 0;
                temp.remove(temp.size()-1);
            }
        }
    }
}

(4)131. 分割回文串(错1)

题解思路1:回溯+动态规划,

class Solution {
    boolean[][] f;
    List<List<String>> ret = new ArrayList<List<String>>();
    List<String> ans = new ArrayList<String>();
    int n;

    public List<List<String>> partition(String s) {
        n = s.length();
        f = new boolean[n][n];
        for (int i = 0; i < n; ++i) {
            Arrays.fill(f[i], true);
        }

        for (int i = n - 1; i >= 0; --i) {
            for (int j = i + 1; j < n; ++j) {
                f[i][j] = (s.charAt(i) == s.charAt(j)) && f[i + 1][j - 1];
            }
        }

        dfs(s, 0);
        return ret;
    }

    public void dfs(String s, int i) {
        if (i == n) {
            ret.add(new ArrayList<String>(ans));
            return;
        }
        for (int j = i; j < n; ++j) {
            if (f[i][j]) {
                ans.add(s.substring(i, j + 1));
                dfs(s, j + 1);
                ans.remove(ans.size() - 1);
            }
        }
    }
}

题解思路2:回溯+记忆化搜索

class Solution {
    int[][] f;
    List<List<String>> ret = new ArrayList<List<String>>();
    List<String> ans = new ArrayList<String>();
    int n;

    public List<List<String>> partition(String s) {
        n = s.length();
        f = new int[n][n];

        dfs(s, 0);
        return ret;
    }

    public void dfs(String s, int i) {
        if (i == n) {
            ret.add(new ArrayList<String>(ans));
            return;
        }
        for (int j = i; j < n; ++j) {
            if (isPalindrome(s, i, j) == 1) {
                ans.add(s.substring(i, j + 1));
                dfs(s, j + 1);
                ans.remove(ans.size() - 1);
            }
        }
    }

    // 记忆化搜索中,f[i][j] = 0 表示未搜索,1 表示是回文串,-1 表示不是回文串
    public int isPalindrome(String s, int i, int j) {
        if (f[i][j] != 0) {
            return f[i][j];
        }
        if (i >= j) {
            f[i][j] = 1;
        } else if (s.charAt(i) == s.charAt(j)) {
            f[i][j] = isPalindrome(s, i + 1, j - 1);
        } else {
            f[i][j] = -1;
        }
        return f[i][j];
    }
}

(5)38. 外观数列

思路:使用一个函数生成对前一项数字的描述,for循环逐次生成。

class Solution {
    public String countAndSay(int n) {
        String str = "1";
        if(n == 1){
            return str;
        }
        for(int i = 2; i <= n; i++){
            str = transfer(str);
        }
        return str;
    }

    public String transfer(String str){
        String res = "";
        int left = 0;
        int right = 1;
        char temp = str.charAt(0);
        while(right <= str.length()){
            while(right < str.length() && str.charAt(right) == temp){
                right++;
            }
            res += (String.valueOf(right - left) + String.valueOf(temp));
            if(right < str.length()){
                temp = str.charAt(right);
            }
            left = right;
            right++;
        }
        return res;
    }
}

(6)132. 分割回文串 II

class Solution {
    public int minCut(String s) {
        int n = s.length();
        boolean[][] g = new boolean[n][n];
        for (int i = 0; i < n; ++i) {
            Arrays.fill(g[i], true);
        }

        for (int i = n - 1; i >= 0; --i) {
            for (int j = i + 1; j < n; ++j) {
                g[i][j] = s.charAt(i) == s.charAt(j) && g[i + 1][j - 1];
            }
        }

        int[] f = new int[n];
        Arrays.fill(f, Integer.MAX_VALUE);
        for (int i = 0; i < n; ++i) {
            if (g[0][i]) {
                f[i] = 0;
            } else {
                for (int j = 0; j < i; ++j) {
                    if (g[j + 1][i]) {
                        f[i] = Math.min(f[i], f[j] + 1);
                    }
                }
            }
        }

        return f[n - 1];
    }
}

(7)59. 螺旋矩阵 II

思路:模拟,flag表示当前方向,对于每种方向而言,发生转向所转的方向是固定的,故只需考虑到各种发生转向的情形。

class Solution {
    public int[][] generateMatrix(int n) {
        int[][] matrix = new int[n][n];
        if(n == 1){
            matrix[0][0] = 1;
            return matrix;
        }
        int flag = 1;
        int cur = 1;
        int i = 0;
        int j = 0;
        while(cur <= n*n){
            matrix[i][j] = cur;
            cur++;
            if(flag == 1){
                if(j < n-1 && matrix[i][j+1] == 0){
                    j++;
                }else{
                    if(matrix[i+1][j] == 0){
                        flag = 2;
                        i++;
                    }else{
                        break;
                    }
                }
            }else if(flag == 2){
                if(i < n-1 && matrix[i+1][j] == 0){
                    i++;
                }else{
                    if(matrix[i][j-1] == 0){
                        flag = 3;
                        j--;
                    }else{
                        break;
                    }
                }
            }else if(flag == 3){
                if(j > 0 && matrix[i][j-1] == 0){
                    j--;
                }else{
                    if(matrix[i-1][j] == 0){
                        flag = 4;
                        i--;
                    }else{
                        break;
                    }
                }
            }else{
                if(i > 0 && matrix[i-1][j] == 0){
                    i--;
                }else{
                    if(matrix[i][j+1] == 0){
                        flag = 1;
                        j++;
                    }else{
                        break;
                    }
                }
            }
        }
        return matrix;
    }
 }

思路2:

class Solution {
    public int[][] generateMatrix(int n) {
        int ub = 0;
        int lb = n-1;
        int left = 0;
        int right = n-1;
        int[][] matrix = new int[n][n];
        int cur = 1;
        while(cur <= n*n){
            if(ub <= lb){
                for(int i = left; i <= right; i++){
                    matrix[ub][i] = cur;
                    cur++;
                }
                ub++;
            }
            if(left <= right){
                for(int i = ub; i <= lb; i++){
                    matrix[i][right] = cur;
                    cur++;
                }
                right--;
            }
            if(ub <= lb){
                for(int i = right; i >= left; i--){
                    matrix[lb][i] = cur;
                    cur++;
                }
                lb--;
            }
            if(left <= right){
                for(int i = lb; i >= ub; i--){
                    matrix[i][left] = cur;
                    cur++;
                }
                left++;
            }
        }
        return matrix;
    }
}

(8)48. 旋转图像

思路:先将矩阵对称,再对矩阵的每一行进行reverse。

class Solution {
    public void rotate(int[][] matrix) {
        int n = matrix.length;
        int temp;
        for(int i = 0; i < n; i++){
            for(int j = i; j < n; j++){
                temp = matrix[i][j];
                matrix[i][j] = matrix[j][i];
                matrix[j][i] = temp;
            }
        }

        for(int i = 0; i < n; i++){
            int left = 0;
            int right = n-1;
            while(left < right){
                temp = matrix[i][left];
                matrix[i][left] = matrix[i][right];
                matrix[i][right] = temp;
                left++;
                right--;
            }
        }
    }
}

(9)54. 螺旋矩阵

思路1:模拟,flag表示当前方向,对于每种方向而言,发生转向所转的方向是固定的,故只需考虑到各种发生转向的情形。对于已经遍历过的位置,将其置为不可能的数,用以标记。

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        int n = matrix.length;
        int m = matrix[0].length;
        
        List<Integer> res = new ArrayList<Integer>();
        if(n == 1 && m == 1){
            res.add(matrix[0][0]);
            return res;
        }
        int flag = 1;
        int count = 1;
        int i = 0;
        int j = 0;
        while(count <= n*m){
            res.add(matrix[i][j]);
            matrix[i][j] = 1000;
            count++;
            if(flag == 1){
                if(j < m-1 && matrix[i][j+1] != 1000){
                    j++;
                }else{
                    if(i < n-1 && matrix[i+1][j] != 1000){
                        flag = 2;
                        i++;
                    }else{
                        break;
                    }
                }
            }else if(flag == 2){
                if(i < n-1 && matrix[i+1][j] != 1000){
                    i++;
                }else{
                    if(j > 0 && matrix[i][j-1] != 1000){
                        flag = 3;
                        j--;
                    }else{
                        break;
                    }
                }
            }else if(flag == 3){
                if(j > 0 && matrix[i][j-1] != 1000){
                    j--;
                }else{
                    if(i > 0 && matrix[i-1][j] != 1000){
                        flag = 4;
                        i--;
                    }else{
                        break;
                    }
                }
            }else{
                if(i > 0 && matrix[i-1][j] != 1000){
                    i--;
                }else{
                    if(j < m-1 && matrix[i][j+1] != 1000){
                        flag = 1;
                        j++;
                    }else{
                        break;
                    }
                }
            }
        }
        return res;

    }
}

思路2:方向变化的规律是一致的,故可以不需要对方向进行标记,在进行遍历的过程中,不断缩小矩阵的范围。

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        int n = matrix.length;
        int m = matrix[0].length;
        int up = 0;
        int down = n-1;
        int left = 0;
        int right = m-1;

        List<Integer> res = new ArrayList<Integer>();
        int count = 0;
        while(count < n*m){
            if(up <= down){
                for(int i = left; i <= right; i++){
                    res.add(matrix[up][i]);
                    count++;
                }
                up++;
            }

            if(left <= right){
                for(int i = up; i <= down; i++){
                    res.add(matrix[i][right]);
                    count++;
                }
                right--;
            }

            if(up <= down){
                for(int i = right; i >= left; i--){
                    res.add(matrix[down][i]);
                    count++;
                }
                down--;
            }

            if(left <= right){
                for(int i = down; i >= up; i--){
                    res.add(matrix[i][left]);
                    count++; 
                }
                left++;
            }
        }
        return res;
    }
}

(10)1288. 删除被覆盖区间

思路:两两区间进行比较,使用一个数组记录是否被删除,遍历完成后,统计没有被删除的数组数量。

class Solution {
    public int removeCoveredIntervals(int[][] intervals) {
        int n = intervals.length;
        int[] deleted = new int[n];
        for(int i = 0; i < n; i++){
            for(int j = i+1; j < n; j++){
                if(deleted[i] == 0 && deleted[j] == 0){
                    int[] temp1 = intervals[i];
                    int[] temp2 = intervals[j];
                    if(temp1[0] <= temp2[0] && temp1[1] >= temp2[1]){
                        deleted[j] = 1;
                    }else if(temp1[0] >= temp2[0] && temp1[1] <= temp2[1]){
                        deleted[i] = 1;
                    }
                }
            }
        }
        int res = 0;
        for(int i = 0; i < n; i++){
            if(deleted[i] == 0){
                res++;
            }
        }
        return res;
    }
}

思路2:贪心算法,

class Solution {
  public int removeCoveredIntervals(int[][] intervals) {
    Arrays.sort(intervals, new Comparator<int[]>() {
      @Override
      public int compare(int[] o1, int[] o2) {
        return o1[0] == o2[0] ? o2[1] - o1[1]: o1[0] - o2[0];
      }
    });

    int count = 0;
    int end, prev_end = 0;
    for (int[] curr : intervals) {
      end = curr[1];
      if (prev_end < end) {
        ++count;
        prev_end = end;
      }
    }
    return count;
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值