刷不动的leetcode系列(五)

255 阅读6分钟

61.给定一个包含 0, 1, 2, ..., n 中 n 个数的序列,找出 0 .. n 中没有出现在序列中的那个数。

示例 1:

输入: [3,0,1] 输出: 2

//自己的等差数列求和公式
class Solution {
public:
    int missingNumber(vector<int>& nums) {
        int n=nums.size();
        int sum=(n*(n+1))/2;
        for(int i=0;i<n;i++)
            sum-=nums[i];
        return sum;
    }
};
//大佬提供的异或操作(^)是一种很好的方式,不用考虑sum越界问题。异或同时满足交换律

举个例子:

    0 ^ 4 = 4
    4 ^ 4 = 0

那么,就可以不用求和,直接使用异或运算^进行 抵消,剩下的数字就是缺失的了。
int missingNumber(vector<int>& nums) {
    int res = nums.size();
    for (int i = 0; i < nums.size(); ++i){
        res ^= nums[i];
        res ^= i;
    }
    return res;
}

62.你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。

假设你有 n 个版本 [1, 2, ..., n],你想找出导致之后所有版本出错的第一个错误的版本。

你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。

示例:

给定 n = 5,并且 version = 4 是第一个错误的版本。

调用 isBadVersion(3) -> false 调用 isBadVersion(5) -> true 调用 isBadVersion(4) -> true

所以,4 是第一个错误的版本。

//二分,没得意思,代码

class Solution {
public:
    int firstBadVersion(int n) {
        int lo = 1;
        int hi = n;
        
        while(lo < hi) {
            int mid = lo + (hi - lo) / 2;
            if (isBadVersion(mid)) {
                hi = mid;
            } else {
                lo = mid + 1;
            }
        }
        return hi;
        
    }
};

63.你和你的朋友,两个人一起玩 Nim 游戏:桌子上有一堆石头,每次你们轮流拿掉 1 - 3 块石头。 拿掉最后一块石头的人就是获胜者。你作为先手。

你们是聪明人,每一步都是最优解。 编写一个函数,来判断你是否可以在给定石头数量的情况下赢得游戏。

示例:

输入: 4 输出: false 解释: 如果堆中有 4 块石头,那么你永远不会赢得比赛; 因为无论你拿走 1 块、2 块 还是 3 块石头,最后一块石头总是会被你的朋友拿走。

//小学的时候奥数题目做过。。。
//大佬的解释巴什博奕,n%(m+1)!=0时,先手总是会赢的
代码:
class Solution {
public:
    bool canWinNim(int n) {
        return n%4;
    }
};

64.你正在和你的朋友玩 猜数字(Bulls and Cows)游戏:你写下一个数字让你的朋友猜。每次他猜测后,你给他一个提示,告诉他有多少位数字和确切位置都猜对了(称为“Bulls”, 公牛),有多少位数字猜对了但是位置不对(称为“Cows”, 奶牛)。你的朋友将会根据提示继续猜,直到猜出秘密数字。

请写出一个根据秘密数字和朋友的猜测数返回提示的函数,用 A 表示公牛,用 B 表示奶牛。

请注意秘密数字和朋友的猜测数都可能含有重复数字。

示例 1:

输入: secret = "1807", guess = "7810"

输出: "1A3B"

解释: 1 公牛和 3 奶牛。公牛是 8,奶牛是 0, 1 和 7。

//传统老套的思想,但是!得用to_string函数!!!!
class Solution {
public:
    string getHint(string secret, string guess) {
        int num1[10]={},num2[10]={};
        int A=0,B=0;
        string res;
        for(int i=0;i<secret.size();i++)
        {
            if(secret[i]==guess[i])
                A++;
            else
            {
                num1[secret[i]-'0']++;
                num2[guess[i]-'0']++;
            }
        }
        for(int i=0;i<10;i++)
            B+=min(num1[i],num2[i]);
        return to_string(A)+'A'+to_string(B)+'B';
        
    }
};

65.给定一个整数数组 nums,求出数组从索引 i 到 j (i ≤ j) 范围内元素的总和,包含 i, j 两点。

示例:

给定 nums = [-2, 0, 3, -5, 2, -1],求和函数为 sumRange()

sumRange(0, 2) -> 1 sumRange(2, 5) -> -1 sumRange(0, 5) -> -3

//越往后题目思路越来越简单但是题目看不懂了。。。。。。
class NumArray {
    public:
    NumArray(vector<int>& nums) {
        int size = nums.size();
        sum.assign(size+1,0);
        int res = 0;
        for(int i = 1; i <= size; ++i) {
            sum[i] = (res+=nums[i-1]);
        }
    }

    int sumRange(int i, int j) {
        return sum[j+1]-sum[i];
    }
    private:
        vector<int> sum;
};

66.给定一个整数,写一个函数来判断它是否是 3 的幂次方。

示例 1:

输入: 27
输出: true
//最大3的幂级数求出来
class Solution {
public:
    bool isPowerOfThree(int n) {
       return n > 0 && 1162261467%n == 0;
    }
};
//利用公式loga C/loga B=logB C
bool isPowerOfThree(int n)
{
        double res = log10(n) / log10(3);
        return (res - (int)(res) == 0) ? true : false;
 }

67.给定一个整数 (32 位有符号整数),请编写一个函数来判断它是否是 4 的幂次方。

示例 1:

输入: 16
输出: true
//先根据上面的检验2的幂,然后4的幂中的1总是在奇数位,用0x5来&
class Solution {
public:
    bool isPowerOfFour(int num) {
        if (num < 0 || num & (num-1))
        return false;
        return num & 0x55555555;
    }
};
//(a^b) % p = ((a % p)^b) % p
由模运算的相关规则,将0X55555
换为		num%3==1

68.编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。

示例 1:

输入:["h","e","l","l","o"] 输出:["o","l","l","e","h"]

//简单题,没啥说的
class Solution {
public:
    void reverseString(vector<char>& s) {
        int n=s.size();
        for(int i=0;i<n/2;i++)
            swap(s[i],s[n-i-1]);
    }
};

69.编写一个函数,以字符串作为输入,反转该字符串中的元音字母。

示例 1:

输入: "hello"
输出: "holle"
//我觉得这题挺简单得,但是!元音我忘了。。。。。
//附上别人写的答案
class Solution {
public:
    string reverseVowels(string s) {
        int i=0,j=s.size()-1;
        string tool="aoeiuAOEIU";
        while(i<j)
        {
            while(tool.find(s[i])==-1&&i<j)
                ++i;
            while(tool.find(s[j])==-1&&i<j)
                --j;
            if(i<j)
                swap(s[i++],s[j--]);
        }
        return s;
    }
};

70.给定两个数组,编写一个函数来计算它们的交集。

示例 1:

输入: nums1 = [1,2,2,1], nums2 = [2,2] 输出: [2]

示例 2:

输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4] 输出: [9,4]

//集合的使用
class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        vector<int>rec;
        unordered_set<int>set1;
        unordered_set<int>set2;
        for(int i =0;i<nums1.size();i++)
            set1.insert(nums1[i]);
        for(int i =0;i<nums2.size();i++)
           if(set1.find(nums2[i])!=set1.end())
               set2.insert(nums2[i]);
        rec.assign(set2.begin(), set2.end());
        return rec;
    }
};