Loading

LeetCode 56-64 until 10-20

56. 合并区间

class Solution {
    public static int[][] mySort(int[][] array){
        Arrays.sort(array, (arr1, arr2) -> arr1[0] == arr2[0] ? arr1[1] - arr2[1] : arr1[0] - arr2[0]);
        return array;
    }
    int FLAG = -2137483641;
    int n = 0;
    public int[][] merge(int[][] intervals) {
        n = intervals.length;
        mySort(intervals);
        // for(int i = 0;i<n;i++){
        for(int i = 0;i<intervals.length;i++){
            // System.out.println(i);
            if(intervals[i][1] == FLAG)continue;
            int l2 = intervals[i][0];
            // consider all the dominant intervals to its left.
            for(int j = 0;j<i;j++){
                if(intervals[j][1] == FLAG){
                    continue;
                }
                int r1 = intervals[j][1];
                if(l2<=r1){
                    // System.out.println("["+intervals[j][0]+","+intervals[j][1]+"] -> ["+intervals[i][0]+","+intervals[i][1]+"]");
                    intervals[j][1] = Math.max(intervals[i][1],intervals[j][1]);
                     // the interval becomes invisable
                    intervals[i][1] = FLAG;
                    n--;
                    break;
                }
            }
        }
        int[][] ans = new int[n][2];
        int num = 0;
        for(int i = 0;i<intervals.length;i++){
            if(intervals[i][1] != FLAG){
                ans[num][0] = intervals[i][0];
                ans[num++][1] = intervals[i][1];
            }
        }
        return ans;
    }
}

注意循环变量是动态的

// for(int i = 0;i<n;i++){
for(int i = 0;i<intervals.length;i++){
	// ...
    n--;
}

循环结束条件的判断是动态的,比如

while(check(nums)){}

57. 插入区间

class Solution {
    int FLAG = -2137483641;
    int n = 0;
     public int[][] merge(int[][] intervals) {
        n = intervals.length;
        // for(int i = 0;i<n;i++){
        for(int i = 0;i<intervals.length;i++){
            if(intervals[i][1] == FLAG)continue;
            int l2 = intervals[i][0];
            // consider all the dominant intervals to its left.
            for(int j = 0;j<i;j++){
                if(intervals[j][1] == FLAG){
                    continue;
                }
                int r1 = intervals[j][1];
                if(l2<=r1){
                    intervals[j][1] = Math.max(intervals[i][1],intervals[j][1]);
                     // the interval becomes invisable
                    intervals[i][1] = FLAG;
                    n--;
                    break;
                }
            }
        }
        int[][] ans = new int[n][2];
        int num = 0;
        for(int i = 0;i<intervals.length;i++){
            if(intervals[i][1] != FLAG){
                ans[num][0] = intervals[i][0];
                ans[num++][1] = intervals[i][1];
            }
        }
        return ans;
    }
    public int[][] insert(int[][] intervals, int[] newInterval) {
        int[][] newIntervals = new int[intervals.length + 1][2];
        // manual sort
        int i = 0;
        while(i<intervals.length && (intervals[i][0] <= newInterval[0] || intervals[i][0] == newInterval[0] && intervals[i][1] <= newInterval[1])){
            newIntervals[i][0] = intervals[i][0];
            newIntervals[i][1] = intervals[i][1];
            i++;
        }
        // insert 
        // (arr1, arr2) -> arr1[0] == arr2[0] ? arr1[1] - arr2[1] : arr1[0] - arr2[0]);
        newIntervals[i][0] = newInterval[0];
        newIntervals[i][1] = newInterval[1];
        i++;
        while(i<=intervals.length){
            newIntervals[i][0] = intervals[i-1][0];
            newIntervals[i][1] = intervals[i-1][1];
            i++;
        }
        return merge(newIntervals);
    }
}

58. 最后一个单词的长度

class Solution {
    public int lengthOfLastWord(String s) {
        String[] ss = s.split(" ");
        return ss.length == 0?0:ss[ss.length - 1].length();
    }
}
class Solution {
    public int lengthOfLastWord(String s) {
        int tail = s.length() - 1,head = tail;
        while(tail>=0 && s.charAt(tail) == ' ')tail --;
        head = tail;
        while(head>=0 && ('A' <= s.charAt(head) &&  s.charAt(head) <= 'Z' || 'a' <= s.charAt(head) &&  s.charAt(head) <= 'z'))head--;
        return tail - head;
    }
}

59. 螺旋矩阵 II

    class Solution {
        public int[][] generateMatrix(int n) {
            int[][] ans = new int[n][n];
            int l = 0,r = n-1,u = 0,b = n-1;
            int count = 0,tar = n*n;
            while(count < tar){
                for(int i = l;i<=r && count < tar;i++)ans[u][i] = ++count;
                u++;
                for(int i = u;i<=b && count < tar;i++)ans[i][r] = ++count;
                r--;
                for(int i = r;i>=l && count < tar;i--)ans[b][i] = ++count;
                b--;
                for(int i = b;i>=u && count < tar;i--)ans[i][l] = ++count;
                l++;
            }
            return ans;
        }
    }

31. 下一个排列

字典序意味着什么

字典序更大,就是在从左到右的某个位置更大

极大字典序序列

倒序

class Solution {
    public void nextPermutation(int[] nums) {
        int tail = nums.length - 1;
        for(;tail - 1 >= 0;tail--){
            // find the last element of the last increasing subsequence
            if(nums[tail - 1] < nums[tail])break;
        }
        int gt = tail + 1;
        for(;gt<nums.length;gt++){
            // find the first element greater than tail, and then replace it
            if(nums[gt] > nums[tail])break;
        }
        if(gt == nums.length){
            // no greater element ahead 
            if(tail - 1 <0)return;
            int temp = nums[tail];
            nums[tail] = nums[tail - 1];
            nums[tail - 1] = temp;
        }else{
            int temp = nums[gt];
            nums[gt] = nums[tail];
            nums[tail] = temp;
            // sort the succeeding elements 
            Arrays.sort(nums,tail+1,nums.length);
        }
    }
}

输入:

[1,3,2]

输出:

[3,1,2]

预期结果:

[2,1,3]

定义错误!

// wrong
nums[tail - 1] < nums[tail];
// right!
nums[tail + 1] > nums[tail]
class Solution {
    public void nextPermutation(int[] nums) {
        if(nums.length == 0)return;

        int tail = nums.length - 2;
        for(;tail>=0;tail--){
            // find the last element of the last increasing subsequence
            if(nums[tail + 1] > nums[tail])break;
        }
        if(tail < 0){
            // reset
            Arrays.sort(nums,0,nums.length);
            return;
        }
        int gt = nums.length - 1;
        for(;gt>=tail + 1;gt--){
            // find the first element greater than tail, and then replace it
            if(nums[gt] > nums[tail])break;
        }
        if(gt == tail){
            // no greater element ahead 
            if(tail - 1 <0)return;
            int temp = nums[tail];
            nums[tail] = nums[tail - 1];
            nums[tail - 1] = temp;
        }else{
            int temp = nums[gt];
            nums[gt] = nums[tail];
            nums[tail] = temp;
            // sort the succeeding elements 
            Arrays.sort(nums,tail+1,nums.length);
        }
    }
}

60. 第k个排列

class Solution {
    boolean done = false;
    int count;
    int[] out;
    void dfs(int l,int n,int k){
        if(l == n){
            count++;

            StringBuilder ans = new StringBuilder();
            for(int i = 0;i<n;i++)ans.append(out[i]);

            System.out.println("i = "+count+" "+ans.toString());
            if(count == k){
                done = true;
            }
            return;
        }
        for(int i = l;i<n;i++){
            int temp = out[i];
            out[i] = out[l];
            out[l] = temp;
            dfs(l+1,n,k);
            if(done)return;
            temp = out[l];
            out[l] = out[i];
            out[i] = temp;
        }
    }   
    public String getPermutation(int n, int k) {
        out = new int[n];
        for(int i = 0;i<n;i++)out[i] = i+1;
        StringBuilder ans = new StringBuilder();
        done = false;
        dfs(0,n,k);
        for(int i = 0;i<n;i++)ans.append(out[i]);
        return ans.toString();
    }
}

输入

5 5

输出

"12543"

差别

预期结果

"12534"

i = 0 l = 0 1|2345
i = 0 l = 1 12|345
i = 0 l = 2 123|45
i = 0 l = 3 1234|5
i = 0 l = 4 12345|
i = 1 l = 3 1235|4
i = 1 l = 4 12354|
i = 2 l = 2 124|35
i = 2 l = 3 1243|5
i = 2 l = 4 12435|
i = 3 l = 3 1245|3
i = 3 l = 4 12453|
// HERE !!!
// 3 should have been selected, while 5 was actually chosen.
i = 4 l = 2 125|34
i = 4 l = 3 1253|4
i = 4 l = 4 12534|
i = 5 l = 3 1254|3
i = 5 l = 4 12543|
i = 6 l = 1 14|235
i = 6 l = 2 142|35
i = 6 l = 3 1423|5
i = 6 l = 4 14235|
i = 7 l = 3 1425|3
i = 7 l = 4 14253|
i = 8 l = 2 143|25
i = 8 l = 3 1432|5
i = 8 l = 4 14325|
i = 9 l = 3 1435|2
i = 9 l = 4 14352|
i = 10 l = 2 145|23
i = 10 l = 3 1452|3
i = 10 l = 4 14523|
i = 11 l = 3 1453|2
i = 11 l = 4 14532|
i = 12 l = 1 12|345
i = 12 l = 2 123|45
i = 12 l = 3 1234|5
i = 12 l = 4 12345|
i = 13 l = 3 1235|4
i = 13 l = 4 12354|
i = 14 l = 2 124|35
i = 14 l = 3 1243|5
i = 14 l = 4 12435|

出错原因

i = 0 l = 2 123|45
i = 2 l = 2 124|35
// HERE !!!
// 3 should have been selected, while 5 was actually chosen.
i = 4 l = 2 125|34

康托展开 O(n^2) / find k-th max

直接计算

class Solution {
    public String getPermutation(int n, int k) {
        int[] fac = new int[n+1];
        fac[0] = 1;
        for(int i = 1;i<=n;i++)fac[i] = fac[i-1] * i;
        k--;

        StringBuilder ans = new StringBuilder();
        boolean[] vis = new boolean[n+1];
        // 1-n can all be used
        for(int i = 0;i<n;i++)vis[i] = false;

        for(int i = 1;i<=n;i++){
            // fill n positions
            int rank = k/fac[n-i] + 1;
            // find the rank-th element
            for(int j = 1;j<=n;j++){
                if(vis[j] == false) rank--;
                if(rank == 0){
                    // and fill the blank            
                    ans.append(j);
                    vis[j] = true;
                    break;
                }
            }
            k %= fac[n-i];
        }
        return ans.toString();
    }
}

61. 旋转链表

class Solution {
    public ListNode rotateRight(ListNode head, int k) {
        if(head == null)return null;
        int len = 0;
        ListNode cur = head,pre = null;
        while(cur != null){
            pre = cur;cur = cur.next;len++;
        }
        pre.next = head;
        int K = len - k%len;
        cur = head;
        for(int i = 0;i<K;i++){
            pre = cur;cur = cur.next;
        }
        pre.next = null;
        return cur;
    }
}

62. 不同路径

class Solution {
    public int uniquePaths(int m, int n) {
        // DP for combinations
        int[][] c = new int[m+n+1][n+1];
        for(int i = 0;i<=m+n;i++)c[i][0] = 1;
        for(int i = 1;i<=m+n;i++){
            for(int j = 1;j<=n;j++){
                c[i][j] = c[i-1][j-1] + c[i-1][j];
            }
        }
        return c[m+n-2][n-1];
    }
}

状态压缩,为什么不能直接转换呢?

class Solution {
    public int uniquePaths(int m, int n) {
        // DP for combinations
        int[]c = new int[m+n+1];
        c[0] = 1;
        for(int i = 1;i<=m+n-2;i++){
            System.out.print(c[0]+" ");
            for(int j = 1;j<i;j++){
                c[j] = c[j-1] + c[j];
                System.out.print(c[j]+" ");
            }
            System.out.println();	
        }
        return c[n-1];
    }
}

1 
1 1 
1 2 2 
1 3 5 5 
1 4 9 14 14 
1 5 14 28 42 42 
1 1 0 0 
1 2 1 0 
1 3 3 1 
1 4 6 4 
1 5 10 10 
1 6 15 20 
1 7 21 35 
1 8 28 56 
class Solution {
    public int uniquePaths(int m, int n) {
        // DP for combinations
        int[]c = new int[m+n+1];
        c[0] = 1;
        for(int i = 1;i<=m+n-2;i++){
            System.out.print(c[0]+" ");
            for(int j = m+n-2;j>=1;j--){
                c[j] = c[j-1] + c[j];
            }
            for(int j = 1;j<=m+n-2;j++){
                System.out.print(c[j]+" ");
            }
            System.out.println();	
        }
        return c[n-1];
    }
}

组合数趋势

组合数->二项分布

63. 不同路径 II

……

int m = obstacleGrid.length;
int n = obstacleGrid.length;
class Solution {
    int FLAG = -0x3f3f3f3f;
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        int m = obstacleGrid.length;
        int n = obstacleGrid[0].length;
        if(m == 0 && n == 0)return 0;
        int[][] c = new int[m][n];
        if(obstacleGrid[0][0] == 1) return 0;
        c[0][0] = 1;
        for(int i = 0;i<m;i++){
            for(int j = 0;j<n;j++){
                if(i ==0 && j == 0)continue;
                int l = j == 0?0:c[i][j-1];
                int u = i == 0?0:c[i-1][j];
                c[i][j] = obstacleGrid[i][j] == 1?0:u+l;
            }
        }
        return c[m-1][n-1];
    }
}

64. 最小路径和

int l = j == 0?INF:c[i][j-1];
int u = i == 0?INF:c[i-1][j];
c[i][j] = Math.min(u,l)+grid[i][j];

小心两个同为INF的情况

for(int i = 0;i<m;i++){
    for(int j = 0;j<n;j++){
        int l = j == 0?INF:c[i][j-1];
        int u = i == 0?INF:c[i-1][j];
        c[i][j] = (l == INF && u == INF) ? grid[i][j] : Math.min(u,l)+grid[i][j];
    }
}
posted @ 2020-11-06 20:35  ZXYFrank  阅读(46)  评论(0编辑  收藏  举报