非科班选手的刷题学习记录Day5

1. 868. 二进制间距

目录

1. 868. 二进制间距

2. 剑指 Offer 40. 最小的k个数

3. 剑指 Offer 48. 最长不含重复字符的子字符串

4. 剑指 Offer 46. 把数字翻译成字符串

C++基础

重写和重载

final关键字


今天继续第一波剑指扫盲,接近尾声了:

1. 868. 二进制间距

难度简单102

给定一个正整数 n,找到并返回 n 的二进制表示中两个 相邻 1 之间的 最长距离 。如果不存在两个相邻的 1,返回 0 。

如果只有 0 将两个 1 分隔开(可能不存在 0 ),则认为这两个 1 彼此 相邻 。两个 1 之间的距离是它们的二进制表示中位置的绝对差。例如,"1001" 中的两个 1 的距离为 3 。

示例 1:

输入:n = 22
输出:2
解释:22 的二进制是 "10110" 。
在 22 的二进制表示中,有三个 1,组成两对相邻的 1 。
第一对相邻的 1 中,两个 1 之间的距离为 2 。
第二对相邻的 1 中,两个 1 之间的距离为 1 。
答案取两个距离之中最大的,也就是 2 。

示例 2:

输入:n = 8
输出:0
解释:8 的二进制是 "1000" 。
在 8 的二进制表示中没有相邻的两个 1,所以返回 0 。

示例 3:

输入:n = 5
输出:2
解释:5 的二进制是 "101" 。

提示:

  • 1 <= n <= 109

简单的位运算题,每次遇到1时记录和上一个1的距离,更新最大距离:

class Solution {

public:

    int binaryGap(int n) {

        int ret = 0;//最远距离,至少为0

        int cnt = 0;//当前处理到第几位

        int pre = -1;//上一个1在第几位

        while(n){

            if(n & 1){//找到一个1

                if(pre != -1){

                    ret = max(ret,cnt - pre);//这不是第一个1,计算距离

                }

                pre = cnt;//更新上一个1的位置

            }

            n >>= 1;

            cnt++;

        }

        return ret;

    }

};

2. 剑指 Offer 40. 最小的k个数

难度简单423

输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。

示例 1:

输入:arr = [3,2,1], k = 2
输出:[1,2] 或者 [2,1]

示例 2:

输入:arr = [0,1,2,1], k = 1
输出:[0]

限制:

  • 0 <= k <= arr.length <= 10000
  • 0 <= arr[i] <= 10000

通过次数330,845提交次数577,315

堆排序(这部分还不是很熟练...),用优先队列实现,要求前K个最小数字,先用前K个元素构成一个大小为K的最大堆,剩余元素只要大于堆顶元素就弹出堆顶并取代。

class Solution {

public:

    vector<int> getLeastNumbers(vector<int>& arr, int k) {

        vector<int> vec(k, 0);

        if (k == 0) {

            return vec;

        }

        priority_queue<int> que;//优先队列(堆)

        for (int i = 0; i < k; i++) {

            que.push(arr[i]);

        }//默认降序排列(最大堆)

        for (int i = k; i < arr.size(); i++) {

            if (que.top() > arr[i]) {

                que.pop();

                que.push(arr[i]);

            }

        }

        for (int i = 0; i < k; ++i) {

            vec[i] = que.top();

            que.pop();

        }

        return vec;

    }

};

3. 剑指 Offer 48. 最长不含重复字符的子字符串

难度中等419

请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。

示例 1:

输入: "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 2:

输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

示例 3:

输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
     请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

提示:

  • s.length <= 40000

这道题做了好几遍了但还是不太顺利TT,双指针+哈希,用right来向右遍历字符串,同时把遍历过的字符加入集合,如果当前字符没有出现过,更新子串长度,如果遇到已经出现过的字符,则向右移动left(子串起点)并删除left所指的字符,直到越过与right指向的字符重复的字符。

class Solution {

public:

    int lengthOfLongestSubstring(string s) {

        if(s.empty()){

            return 0;

        }

        int ret = 1;

        int left = 0,right = 0;

        unordered_set<char> occured;

        while(right < s.size()){

            while(occured.count(s[right])){

                occured.erase(s[left]);

                left++;

            }

            occured.insert(s[right]);

            ret = max(ret,right - left + 1);

            right++;

        }

        return ret;

    }

};

4. 剑指 Offer 46. 把数字翻译成字符串

难度中等423

给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。

示例 1:

输入: 12258
输出: 5
解释: 12258有5种不同的翻译,分别是"bccfi", "bwfi", "bczi", "mcfi"和"mzi"

提示:

  • 0 <= num < 231

通过次数175,859提交次数336,028

一个动态规划题,青蛙跳台阶的变种。

递推关系:如果新加的字符和上一个字符能组成26以内的数,则说明这两个字符可以单独翻译,也可以合成一个字符串翻译。前者的方法个数=不加新字符的方法数,后者的方法个数=不加新字符和前一个字符的方法数,相当于跳到某台阶的方法数=跳到前一级和前两级台阶的方法数之和。

这题位运算有点麻烦,直接转成字符串顺序处理比较方便,注意char转int要-‘0’。

class Solution {

public:

    int translateNum(int num) {

        vector<int> dp(10);//最大2147483647

        dp[0] = 1;

        int cur = 0;//当前位的数字

        int pre = 0;//上一位的数字

        string temp = to_string(num);

        if(temp.size() == 1){

            return 1;

        }

        if((temp[0] - '0') * 10 + temp[1] - '0' < 26 && temp[0] != '0'){

            dp[1] = 2;

        }

        else dp[1] = 1;

        pre = temp[1] - '0';

        for(int i = 2; i < temp.size(); i++){

            cur = temp[i] - '0';

            if(cur + pre * 10 < 26 && pre){

                dp[i] = dp[i - 1] + dp[i - 2];

            }

            else{

                dp[i] = dp[i - 1];

            }

            pre = cur;

        }

        return dp[temp.size() - 1];

    }

};

C++基础

重写和重载

重写是子类对父类函数的重写,是子类和父类之间多态性的一种体现。如果在子类中定义了和父类中某函数名称、参数、返回值类型相同的函数,则该函数被重写。

重载是在一个类中定义了多个同名函数方法,是一个类中多态性的体现。

final关键字

final可以用于修饰类,表示这个类不可以再被继承;

也可以用于修饰方法,表示这个方法不可以被重写。

**后面打算三四天一更,以便每次能多积累一点题/知识点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值