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];
}
}
本博文本意在于记录个人的思考与经验,部分博文采用英语写作,可能影响可读性,请见谅
本文来自博客园,作者:ZXYFrank,转载请注明原文链接:https://www.cnblogs.com/zxyfrank/p/13938810.html