【Notes16】剑指offer_41-50题


41.数据流中的中位数

在这里插入图片描述

//java版
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();
    } 
}
//C++版
class Solution {
    
    
public:
    
    //例子
    //输入:1, 2, 3, 4
    //输出:1,1.5,2,2.5
    
    //大小根堆
    //小根堆 较大的数字 最小的是根节点
    //大根堆 较小的数字 最大的是根节点
    //大根堆 - 小根堆 = 1/0
    
    priority_queue<int> maxheap;
    priority_queue<int, vector<int>, greater<int>> minheap;
    
    void Insert(int num)
    {
    
    
        //都无脑先插入 大根堆
        maxheap.push(num);
        
        //大根堆 - 小根堆 = 1/0
        if(maxheap.size() - minheap.size() > 1)
        {
    
    
            //从大根堆中拿最大的元素到小根堆
            minheap.push(maxheap.top());
            maxheap.pop();
        }
        
        //插入的元素较大
        //大根堆的根  > 小根堆的根 
        //交换
        while(minheap.size() && maxheap.top() > minheap.top())
        {
    
    
            int max = maxheap.top(), min = minheap.top();
            maxheap.pop(), minheap.pop();
            maxheap.push(min), minheap.push(max);
        }
    }

    double GetMedian()
    {
    
     
        //奇数
        if((maxheap.size() + minheap.size()) % 2 == 1) return maxheap.top();
        //偶数
        return (maxheap.top() + minheap.top()) /2.0;
    }

};

42.连续子数组的最大和

在这里插入图片描述

//java版
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;
    }
}
//C++版
class Solution {
    
    
public:
    //面试高频
    int FindGreatestSumOfSubArray(vector<int> array) {
    
    
        int res = INT_MIN, s = 0;
        //x 10  -11 3 4
        //s 10  -1  3 7
        //r 10   10 10 10
        for(auto x : array)
        {
    
    
            if(s < 0) s = 0;
            s += x;
            res = max(res, s);
        }
        
        return res;
    }
};

43.1~n整数中1出现的次数

在这里插入图片描述

//java版
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;
    }
}
//C++版
class Solution {
    
    
public:
    //13  6
    //left i  right
    //i 1  left * 10^i + right + 1
    //i 0 left *10 ^ i + 10^i 
    int NumberOf1Between1AndN_Solution(int n)
    {
    
    
        if(!n) return 0;
        //n >= 1
        vector<int> num;
        while(n)
        {
    
    
            num.push_back(n % 10);
            n /= 10;
        }
        
        int res = 0;
        for(int i = num.size() - 1; i >= 0; i --)
        {
    
    
            int left = 0, right = 0, x = 1;
            //高位到低位 left
            for(int j = num.size() - 1; j > i; j --)
                left = left * 10 + num[j];
            //计算低位 right
            for(int k = i - 1; k >= 0; k --)
            {
    
    
                right = right * 10 + num[k];
                x *= 10;
            }
            
            //计算位数
            res = res + left * x;
            if(num[i] == 1) res += right + 1;
            else if(num[i] > 1) res += x;
            
        }
        return res;
    }
};

44.数字序列中某一位的数字

在这里插入图片描述

//java版
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';
    }
}
//C++版
class Solution {
    
    
public:
    int digitAtIndex(int n) {
    
    
     if(!n) return 0;
     //确定是几位数
     //i 位数
     long long i = 1, s = 9, base = 1;
     while(n > i * s)
     {
    
    
         n -= i * s;
         i ++;
         s *= 10;
         base *= 10;
     }
     //确定是几位数的第几个数
     //number 确定第几个数
     //eg 4 位数的 第 1000 位属于哪个数
     // 1000 / 4 = 250
     // n + i - 1 / i下取整 == n/ i上取整
     int number = base + (n + i - 1)/ i - 1;
     //确定是该数的第几个数字
     //r如果取模 != 0 就是 对应的数字 否则 == 0就是最后一位 即 i
     int r = n % i ? n % i : i;
     for(int j = 0; j < i - r; j ++) number /= 10;
     
     return number % 10;
    }
};

45.把数组排成最小的数

在这里插入图片描述

//java版
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);
    }
}
//C++版
class Solution {
    
    
public:
    static bool cmp(int a, int b)
    {
    
    
        string as = to_string(a), bs = to_string(b);
        //33 321
        //“33321” “32133”
        return as + bs < bs + as;
    }
    
    string PrintMinNumber(vector<int> nums) {
    
    
        //33  321
        //33321 32133
        sort(nums.begin(), nums.end(),cmp);
        
        string res;
        for(auto x : nums) res += to_string(x);
        return res;
    }
};

46.把数字翻译成字符串

在这里插入图片描述

//java版
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;
    }
}
//C++版
class Solution {
    
    
public:
    int getTranslationCount(string s) {
    
    
        //动态规划
        //fi  = fi-1 +  fi-2
        // >=10  <=25
        int n = s.size();
        vector<int> f(n + 1);
        f[0] = 1;
        for(int i = 1; i <= n; i ++)
        {
    
    
            f[i] = f[i - 1];
            //什么时候加上f i -2
            //s[i - 2]s[i - 1]  >= 10 <= 25
            int t = (s[i - 2] - '0') * 10 + s[i - 1] - '0';
            if(t >= 10 && t <= 25)
                f[i] += f[i - 2];
        }
        
        return f[n];
    }
};

47.礼物的最大价值

在这里插入图片描述

//java版
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];
    }
}
//C++版
class Solution {
    
    
public:
    int getMaxValue(vector<vector<int>>& grid) {
    
    
        int x = grid.size(), y = grid[0].size();

        vector<vector<int>> f(x + 1, vector<int>(y + 1));
        for(int i = 1; i <= x; i ++)
            for(int j = 1; j <= y; j ++)
                f[i][j] = max(f[i -1][j], f[i][j - 1]) + grid[i - 1][j - 1];
        //f[1][1]  grid[0][0]

        return f[x][y];
    }
};

48.最长不含重复字符的子字符串

在这里插入图片描述

//java版
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;
    }
}
//C++版
class Solution {
    
    
public:
    int longestSubstringWithoutDuplication(string s) {
    
    
        unordered_map<char, int> hash;
        
        int res = 0;
        for(int i = 0, j = 0; j < s.size(); j ++)
        {
    
    
            hash[s[j]] ++;
            while(hash[s[j]] > 1)//s[j]字符出现两次
            {
    
    
                hash[s[i]] --;
                i ++;;
            }
            res = max(res, j - i + 1);
        }
        
        return res;
    }
};

49.丑数

在这里插入图片描述

//java版
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];
    }
}
//C++版
class Solution {
    
    
public:
    int GetUglyNumber_Solution(int n) {
    
    
        if(n < 7) return n;
        vector<int> chou(1,1);
        int i = 0, j = 0, k = 0;
        while(-- n)//循环n-1次
        {
    
    
            int t = min(chou[i] * 2, min(chou[j] * 3, chou[k] * 5));
            chou.push_back(t);
            if(t == chou[i] * 2) i ++;//SI  2
            if(t == chou[j] * 3) j ++;//SJ  3
            if(t == chou[k] * 5) k ++;//SK  5
        }
        
        return chou.back();
    }
};

50.第一个只出现一次的字符

在这里插入图片描述

//java版
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 ' ';
    }
}
//C++版
class Solution {
    
    
public:
    int FirstNotRepeatingChar(string str) {
    
    
        //针对第一次出现的字符/数字
        unordered_map<char, int> hash;
        for(auto c : str) hash[c] ++;
        
        int res = -1;
        int index = 0;
        for(auto c : str)
        {
    
    
            if(hash[c] == 1)
            {
    
    
                res = index;
                break;
            }
            index ++;
        }        
        return res;
    }
};

猜你喜欢

转载自blog.csdn.net/weixin_43435675/article/details/107237563