classSolution { publicintfindKthNumber(int n, int k) { intans=1; while (k > 1) { intcnt= getCnt(ans, n); // 说明所有以x为前缀的数组均可跳过,此时让x自增,k减去cnt。含义为从下一个[数值比x大]的前缀中找目标值 if (cnt < k) { k -= cnt; ans ++; // 说明目标值前缀必然为x,此时,我们需要在以x为前缀的前提下找目标值. // 此时让 x 乘 10,k 减 1,含义为从下一个[字典序比x大]的前缀中寻找目标值 // 当 k == 1时候,当前前缀x即是答案(含义为以x为前缀的所有数中,最小的数,也就是x本身) } else { k--; ans *= 10; } } return ans; } /** 在范围[1, limit]内,以x为前缀的数值数量等于下面所有情况的数量之和 位数为 n 的数:仅有 x 本身,共1个 位数为 n + 1 < m 的数,有 x0 到 x9,共10个 位数为 n + 2 < m 的数,有 x00 到 x99,共100个 ... 位数为m的数,要根据limit长度与x等同的前缀u 和 x 的大小关系。进一步分情况讨论 u < x:此时所有位数为m的数均大于limiy,合法个数为0 u == x,此时所有位数为m的数中部分满足limit限制的合法个数为 limit - x * 10^k + 1 只有[x0...0, limit] 合法 u > x:此时所有位数为m的数均小于limit,合法个数为 10 ^ k */ publicintgetCnt(int x, int limit) { Stringa= String.valueOf(x), b = String.valueOf(limit); intn= a.length(), m = b.length(), k = m - n; intans=0, u = Integer.parseInt(b.substring(0, n)); for (inti=0; i < k; i++) ans += Math.pow(10, i); if (u > x) ans += Math.pow(10, k); elseif (u == x) ans += limit - x * Math.pow(10, k) + 1; return ans; } }
classSolution { publicintfindKthNumber(int n, int k) { int cur=1;//第一字典序小的(就是1) int prefix=1;// 前缀从1开始 while(cur<k) { int tmp=getCnt(n,prefix); //当前prefix峰的值 if(tmp+cur>k) {// 找到了 prefix*=10; //往下层遍历 cur++;//一直遍历到第K个推出循环 }else { prefix++;//去下个峰头(前缀)遍历 cur+=tmp;//跨过了一个峰(前缀) } }//退出循环时 cur==k 正好找到 return prefix; }
privateintgetCnt(int n, int prefix) { //不断向下层遍历可能一个乘10就溢出了, 所以用long long cur=prefix; long next=cur+1;//下一个前缀峰头 int count=0; while(cur<=n) { count+=Math.min(n+1,next)-cur;//下一峰头减去此峰头 // 如果说刚刚prefix是1,next是2,那么现在分别变成10和20 // 1为前缀的子节点增加10个,十叉树增加一层, 变成了两层 // 如果说现在prefix是10,next是20,那么现在分别变成100和200, // 1为前缀的子节点增加100个,十叉树又增加了一层,变成了三层 cur*=10; next*=10; //往下层走 } return count; } }
publicintreversePairsProcess(int[] nums, int L, int R) { if (L >= R) return0; intM= L + (R - L) / 2; return reversePairsProcess(nums, L, M) + reversePairsProcess(nums, M + 1, R) + mergeTwo(nums, L, M, R);
}
publicintmergeTwo(int[] nums, int L, int M, int R) { intp1= L, p2 = M + 1; int[] help = newint[R - L + 1]; intreversePairs=0; intindex=0; while (p1 <= M && p2 <= R) { reversePairs += nums[p1] > nums[p2] ? (M - p1 + 1) : 0; help[index++] = nums[p1] > nums[p2] ? nums[p2++] : nums[p1++]; }
while (p1 <= M) { help[index++] = nums[p1++]; } while (p2 <= R) { help[index++] = nums[p2++]; } for (inti=0; i < help.length; i++) { nums[L + i] = help[i]; } return reversePairs; } }