Notes6剑指offer_41-68题
Posted 码农编程录
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Notes6剑指offer_41-68题相关的知识,希望对你有一定的参考价值。
文章目录
- 41.数据流中的中位数
- 42.连续子数组的最大和
- 43.1~n整数中1出现的次数
- 44.数字序列中某一位的数字
- 45.把数组排成最小的数
- 46.把数字翻译成字符串
- 47.礼物的最大价值
- 48.最长不含重复字符的子字符串
- 49.丑数
- 50.第一个只出现一次的字符
- 51.数组中的逆序对
- 52.两个链表的第一个公共节点
- 53.在排序数组中查找数字 I
- 54.二叉搜索树的第k大节点
- 55.二叉树的深度
- 56.数组中数字出现的次数
- 57.和为s的两个数字
- 58.翻转单词顺序
- 59.滑动窗口的最大值
- 60.n个骰子的点数
- 61.扑克牌中的顺子
- 62.圆圈中最后剩下的数字
- 63.股票的最大利润
- 64.求1+2+…+n
- 65.不用加减乘除做加法
- 66.构建乘积数组
- 67.把字符串转换成整数
- 68.二叉搜索树的最近公共祖先
41.数据流中的中位数
class MedianFinder {
//大根堆 + 小根堆
//大根堆 堆顶 存的是最大的数字 小的那一半
//小根堆 堆顶 存的是最小的数字 大的那一半
Queue<Integer> A, B;
/** initialize your data structure here. */
public MedianFinder() {
A = new PriorityQueue<>();//小根堆 存大的一半数字
B = new PriorityQueue<>((x,y) -> (y - x));//大根堆 存小的一半数字
}
public void addNum(int num) {
//无脑放进小根堆
//如果 小根堆的数字数量 > 大根堆的数字数量了
//把小根堆中较小数字 放进大根堆
if(A.size() != B.size())
{
A.add(num);//无脑放进小根堆
B.add(A.poll());//把小根堆中较小数字 放进大根堆
}else
{
//堆顶比较 确保大小根堆的 一半的特性
B.add(num);//大数字 在堆顶
A.add(B.poll());//通过添加堆顶数字 确保 特性
}
}
public double findMedian() {
return A.size() == B.size() (A.peek() + B.peek())/2.0 : A.peek();
}
}
42.连续子数组的最大和
class Solution {
public int maxSubArray(int[] nums) {
int res = nums[0];//最大子数组的和
for(int i = 1; i < nums.length; i ++){
//动态规划
//dp[i]到i位置 最大子数组的和
//dp[i - 1] nums[i]
nums[i] += Math.max(nums[i - 1], 0);
res = Math.max(res, nums[i]);
}
return res;
}
}
43.1~n整数中1出现的次数
class Solution {
public int countDigitOne(int n) {
//high cur low
//4507
// cur == 0 high * 10^i
//high 45 cur 0 low 7
// 4507
// 0010 - 4419
// 000 - 449 450个数字
//cur == 1 high* 10^i + low + 1
//4517
//high 45 cur 1 low 7
//0010 4517
//000 - 457 458个数字
//cur == 2 3 4...9 (high+1) * 10^i
//4527
//high 45 cur 2 low 7
// 0010 - 4519
// 000 - 459 460个数字
int x = 1, res = 0;
int high = n / 10, cur = n % 10, low = 0;
while(high != 0 || cur != 0){
if(cur == 0) res += high * x;
else if(cur == 1) res += high * x + low + 1;
else res += (high + 1) * x;
low += cur * x;
cur = high % 10;
high /= 10;
x *= 10;
}
return res;
}
}
44.数字序列中某一位的数字
class Solution {
public int findNthDigit(int n) {
//第一步 确定n在哪个 数位的数中 1 2 3
//1 9
//10 99
//100 999
int digit = 1;
long start = 1;
long count = 9;
while(n > count){//得到了digit
n -= count;
digit += 1;
start *= 10;
count = digit * start * 9;//对于 2 个数字组成的10- 99 180 2*90
}
//第二步:确定在哪个数字中 15
long num = start + (n - 1)/digit;
//第三步:找到确定的1位的数字
return Long.toString(num).charAt((n - 1) % digit) - '0';
}
}
45.把数组排成最小的数
class Solution {
public String minNumber(int[] nums) {
String[] str = new String[nums.length];
for(int i = 0; i < nums.length; i ++){
str[i] = String.valueOf(nums[i]);
}
//字符串排序
strsort(str, 0, str.length - 1);//快排
//Arrays.sort(str,(x,y) -> (x + y).compareTo(y + x));//内置函数
//字符串数组依次组合
StringBuilder res = new StringBuilder();
for(String s : str){
res.append(s);
}
return res.toString();
}
void strsort(String[] str, int l, int r){
//快排写法
if(l >= r) return;
int i = l, j = r;
String temp = str[i];
while(i < j){
while((str[j] + str[l]).compareTo(str[l] + str[j]) >= 0 && i < j) j --;
while((str[i] + str[l]).compareTo(str[l] + str[i]) <= 0 && i < j) i ++;
temp = str[i];
str[i] = str[j];
str[j] = temp;
}
str[i] = str[l];
str[l] = temp;
strsort(str, l, i - 1);
strsort(str, i + 1, r);
}
}
46.把数字翻译成字符串
class Solution {
public int translateNum(int num) {
// 0 ~ 25有意义
//dp【i】 = dp【i - 1】 (+ dp【i - 2】)
String s = String.valueOf(num);
int a = 1, b = 1;
for(int i = 2; i <= s.length(); i ++){
String temp = s.substring(i - 2, i);
int c = temp.compareTo("10") >= 0 && temp.compareTo("25") <= 0 a + b : a;
b = a;
a = c;
}
return a;
}
}
47.礼物的最大价值
class Solution {
public int maxValue(int[][] f) {
//最经典二维动态规划
//f[i][j] = max(f[i-1][j], f[i][j - 1])
int m = f.length, n = f[0].length;
for(int i = 0; i < m; i ++)
for(int j = 0; j < n; j ++){
if(i == 0 && j == 0) continue;
if(i == 0) f[i][j] += f[i][j - 1];
else if(j == 0) f[i][j] += f[i - 1][j];
else f[i][j] += Math.max(f[i - 1][j], f[i][j - 1]);
}
return f[m - 1][n - 1];
}
}
48.最长不含重复字符的子字符串
class Solution {
public int lengthOfLongestSubstring(String s) {
HashMap<Character, Integer> hash = new HashMap<>();
int res = 0, left = 0;
for(int i = 0; i < s.length(); i ++){
char c = s.charAt(i);
//判断c是否出现过
//"abcabcbb"
if(hash.containsKey(c)){
left = Math.max(left, hash.get(c) + 1);
}
hash.put(c, i);
res = Math.max(res, i - left + 1);
}
return res;
}
}
49.丑数
class Solution {
public int nthUglyNumber(int n) {
int[] f = new int[n];//前n个丑数
int[] pos = new int[3];//对应 2 3 5三个质因子
f[0] = 1;//第一个丑数1
for(int i = 1; i < n; i ++)
{
int a = f[pos[0]] * 2;
int b = f[pos[1]] * 3;
int c = f[pos[2]] * 5;
int mini = Math.min(Math.min(a, b), c);//一定只包含 2 3 5质因子
if(f[pos[0]] * 2 == mini) pos[0] ++;//6 2*3 10 2*5
if(f[pos[1]] * 3 == mini) pos[1] ++;//6 3*2
if(f[pos[2]] * 5 == mini) pos[2] ++;// 10 5*2
f[i] = mini;
}
return f[n - 1];
}
}
50.第一个只出现一次的字符
class Solution {
public char firstUniqChar(String s) {
///hash表
HashMap<Character, Boolean> hash = new HashMap<>();
char[] ch = s.toCharArray();
for(char c : ch)
hash.put(c, !hash.containsKey(c));//先插入 true,如果重复了就变成false
for(char c : ch)
if(hash.get(c)) return c;
return ' ';
}
}
51.数组中的逆序对
class Solution {
//归并排序
public int reversePairs(int[] nums) {
int len = nums.length;
if(len < 2)//逆序对要求两个数字以上
return 0;
int[] temp = new int[len];
return mergeSort(nums, 0, len - 1, temp);
}
private int mergeSort(int[] nums, int left, int right, int[] temp){
//递归终止条件
if(left >= right)
return 0;
int mid = left + (right - left) / 2;//防止溢出
//[left, mid]
int leftPairs = mergeSort(nums, left, mid, temp);
//[mid + 1, right]
int rightPairs = mergeSort(nums, mid +1, right, temp);
//[left mid] [mid + 1 right]
if(nums[mid] <= nums[mid + 1]){
return leftPairs + rightPairs;
}
//跨区间的逆序对
int crossPairs = mergeSortCross(nums, left, mid, right, temp);
return leftPairs + rightPairs + crossPairs;
}
private int mergeSortCross(int[] nums, int left,int mid, int right, int[] temp){
for(int i = left; i <= right; i ++)
temp[i] = nums[i];
int i = left;
int j = mid + 1;
//[left i mid] [mid + 1 j right]
// mid - i + 1个逆序对
int count = 0;
for(int k = left; k <= right; k ++)以上是关于Notes6剑指offer_41-68题的主要内容,如果未能解决你的问题,请参考以下文章