Leetcode Daily

文章目录

342. 4的幂

#include <cmath>
#include<algorithm>
class Solution {
public:
    bool isPowerOfFour(int n) {
     // log(4^n) = n *log(4)
        long x = 1;
        while(x<n){
            x = x<<2;
        }
        return x==n;
    }
};
// 100000000
// 4 16 64 256 
// 100 
// 011
// 10000
// 1000000


// 4
// n&&(n-1)==0

1744. 你能在你最喜欢的那天吃到你最喜欢的糖果吗?

tips: 前缀法
计算2个区间,第一个是截止到favoriteDay的时候,一共最快或者最慢吃的糖果数量[x1, y1]。
第二个区间是截止到favoriteDay的时候,想吃的糖果type编号的范围[x2, y2]。
如果第一个区间中有想吃糖果type的编号,也就是2个区间有交集,那么为True。

// 构造 sum[i] = sum[i - 1] + candiesCount[i]
class Solution {
public:
    vector<bool> canEat(vector<int>& candiesCount, vector<vector<int>>& queries) {
        int l1 = candiesCount.size();
        int l2 = queries.size();
        vector<long long> sum(l1);
        sum[0] = candiesCount[0];
        for(int i = 1; i < l1; i++){
            sum[i] = sum[i - 1] + candiesCount[i];
        }
        vector<bool> ans;
        for(int i = 0; i < l2; i++){
            int type = queries[i][0];
            int day = queries[i][1];
            int capi = queries[i][2];
            // [x1, y1]
            // slowest
            long long x1 = day+1;
            // fastest
            long long y1 =(day + 1) * (long long)capi;
            // [x2, y2]
            long long x2 = (type < 1 ? 1 : sum[type - 1] + 1);
            long long y2 = sum[type];
            ans.push_back(!(x1>y2||y1<x2));
                
            
        }

        return ans;

        
    }
};


523. 连续的子数组和

前缀法 + 同余定理 + 无序表;
不能暴力解,会超时;
考虑到同余定理以及减少复杂度,就要用到统计出现相同余数的nums的index。用到map中的count方法。

//当 prefixSums}[q]-prefixSums[p] 为 k的倍数时,prefixSums}[p]和 prefixSums[q] 除以 k 的余数相同
//
class Solution {
public:
    bool checkSubarraySum(vector<int>& nums, int k) {
        int m = nums.size();
        // 满足第一个条件。
        if (m < 2) {
            return false;
        }
        
        // 前缀法
        vector<int> sum(m);
        sum[0] = nums[0];
        for(int i = 1; i < m; i++){
            sum[i] = sum[i-1] + nums[i];
        }
        // 默认int int的无序表中的元素值为0
        unordered_map<int, int> map;
        map[0] = -1;

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

            int s = sum[i] % k;
            // 如果找到 计算len
            if(map.count(s)){
                int len = i - map[s];
                if(len >=2)
                    return true;
            }
            // 没有找到,存入余数为s时的最先的index的位置。
            else{
                map[s] = i;
            }  
        }
        return false;
    }
};



525. 连续数组

给定一个二进制数组 nums , 找到含有相同数量的 01 的最长连续子数组,并返回该子数组的长度。

输入: nums = [0,1]
输出: 2
说明: [0, 1] 是具有相同数量0和1的最长连续子数组。
输入: nums = [0,1,0]
输出: 2
说明: [0, 1] (或 [1, 0]) 是具有相同数量0和1的最长连续子数组。
class Solution {
public:
    int findMaxLength(vector<int>& nums) {
        int m = nums.size();
        vector<int> sum(m);
        vector<int> cons(m);
        unordered_map<int, int> map;
        for(int i = 0; i < m; i++){
            if(nums[i] == 1)
                cons[i] = 1;
            else
                cons[i] = -1;
        }

        sum[0] = cons[0];
        for(int i = 1; i < m; i++){
            sum[i] = sum[i - 1] + cons[i];
        }

        map[0] = -1;
        // cout<< map[-1];
        int maxlength = 0;
        int cnt = 0;
        for(int i = 0; i < m; i++){
            if(map.count(sum[i])){ // map.count(-1)
                int index = map[sum[i]];
                maxlength = max(maxlength, i - index);
            }else{
                map[sum[i]] = i;
            }
 
        }
    return maxlength;
    }
};


160. 相交链表


/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if( headA == NULL || headB == NULL)
            return NULL;
        ListNode *headb_head;
        headb_head = headB;
        while(headA != NULL){  
            while(headB != NULL){
                if(headB == headA){
                    return headB;   
                }
                headB = headB->next;
            }
            headA = headA->next;
            headB = headb_head;
        }
        return NULL;     

    // 哈希集合方法
/*


        unordered_set<ListNode*> set;
        ListNode* temp;
        temp = headA;
        while(temp != NULL){
            set.insert(temp);
            temp = temp->next;
        }

        temp = headB;
        while(temp != NULL){
            if(set.count(temp))
                return temp;
            temp = temp->next;
        }    

        return NULL;
*/
    }


/* 双指针

        if(headA == NULL || headB == NULL)
            return NULL;
        ListNode *pa = headA, *pb = headB;        
        while(pa != pb){
            if(pa == NULL){
                pa = headB;
            }else{
                pa = pa->next;
            }
            if(pb == NULL){
                pb = headA;
            }else{
                pb = pb->next;
            }
        }
        return pa;
*/
};




203. 移除链表元素

因为有可能链表头所在的元素就是等于val,需要移除,因此考虑temp->next = temp->next->next;以及temp->next->val != val的时候,就有一个缺漏,头结点没有考虑。这题的关键在于构造一个哑结点dummyNodedummyNode = head->next,其次在最后返回的时候,temp已经修改了链表连接的元素,需要return dummyNode->next

其中哑结点的构造有ListNode以及ListNode*两种类型,问了师兄以后,应该这么写:

ListNode p = ListNode(0);
ListNdoe *p = new ListNode(0); // 必须要有new 不然无法构建指针变量
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        if(head == nullptr)
            return nullptr;
        ListNode* dummyNode = new ListNode(0);
        dummyNode->next = head;
        ListNode* temp = dummyNode;
        while(temp->next != nullptr){
            if(temp->next->val != val){
                temp = temp->next;
            }else{
                temp->next = temp->next->next;

            }
        }
        return dummyNode->next;
        
        /*
        // 递归 其实就是之前想的从前往后,但是当时没法确定如果当前元素等于val,那前一个元素怎么获得的问题,但是反思了一下这个就是递归。

        if(head == nullptr)
            return head;
        head->next = removeElements(head->next, val);
        return head->val == val? head->next:head;
        */
    }
};




474. 一和零

DP

class Solution {
public:
    vector<int> getZerosOnes(string &str){

        int length = str.length();
        vector<int> zerosOnes(2);
        for(int i =0; i < length; i++){
            zerosOnes[ str[i]-'0' ] ++;        
        }
        return zerosOnes;

    }
    int findMaxForm(vector<string> &strs, int m, int n){

        int length = strs.size();
        vector<vector<vector<int>>> dp(length + 1, vector<vector<int>>(m + 1, vector<int>(n + 1)));
        for(int i = 1; i <= length; i++){
            vector<int> zerosOnes = getZerosOnes(strs[i-1]);
            int zeros = zerosOnes[0], ones = zerosOnes[1];
            for(int j = 0; j <= m; j++){
                for(int k =0; k <= n; k++){
                    dp[i][j][k] = dp[i - 1][j][k];
                    if(j>=zeros && k>=ones){
                        int a = dp[i - 1][j][k];
                        int b = dp[i - 1][j - zeros][k - ones] + 1;
                        dp[i][j][k] = max(a, b);
                    }
                }
            }
        
        }

        return dp[length][m][n];

    }
};

797. 所有可能的路径

dfs

class Solution {
public:
    vector<vector<int>> ans;
    vector<int> temp;
    vector<vector<int>> allPathsSourceTarget(vector<vector<int>>& graph) {

        dfs(graph, 0);
        return ans;
    }

    void dfs(vector<vector<int>> graph, int index){
        temp.push_back(index);
        if(index == graph.size()-1){
            ans.push_back(temp);
            temp.pop_back();
            return;
        }
        for(int i = 0; i < graph[index].size(); i++){
            dfs(graph, graph[index][i]);
        }
        temp.pop_back();
    }
};

/*


*/

494. 目标和

回溯

class Solution {
public:
    int count = 0;
    int findTargetSumWays(vector<int> &nums, int target){
        backtrack(nums, target, 0, 0);
        return count;
    }

    void backtrack(vector<int> &nums, int target, int index, int sum){
        
        if(index == nums.size()){
            if(sum == target){
                count++;
            }
        }else{
            backtrack(nums, target, index + 1, sum + nums[index]);
            backtrack(nums, target, index + 1, sum - nums[index]);
        }

    }


};


// 动态规划

class Solution {
public:
    //int count = 0;
    int findTargetSumWays(vector<int> &nums, int target){
        // backtrack(nums, target, 0, 0);

        int n = nums.size();
        int sum = accumulate(nums.begin(), nums.end(), 0);
        int neg = (sum - target);
        if(neg % 2 != 0 || neg < 0)
            return 0;
        neg = neg / 2;
        vector<vector<int>> dp(n+1, vector<int>(neg+1));
        dp[0][0] = 1;
        for(int i = 1; i <=n; i++){
            int num = nums[i-1];
            for(int j = 0; j <=neg; j++){
                dp[i][j] = dp[i-1][j];
                if(j>=num){
                    dp[i][j] = dp[i-1][j] + dp[i-1][j-num];
                }
            }
        }

        return dp[n][neg];
    }

1049. 最后一块石头的重量 II

 // sum - 2*x  当x = mid时,x最大 sum最小
class Solution {
public:
    int lastStoneWeightII(vector<int>& stones) {
        int len = stones.size();
        int sum = accumulate(stones.begin(), stones.end(), 0);
        int mid = sum/2;
        vector<vector<int>> dp(len+1, vector<int>(mid+1));

        for(int i = 1; i <= len; i++){
            for(int j = 0; j <= mid; j++){
                dp[i][j] = dp[i-1][j];
                if(j >= stones[i-1]){
                    dp[i][j] = max(dp[i-1][j], dp[i-1][j-stones[i-1]] + stones[i-1]);
                }
            }
        }
        return sum - 2*dp[len][mid];
    }
};

879. 盈利计划

class Solution {
public:
    int profitableSchemes(int n, int minProfit, vector<int>& group, vector<int>& profit) {
        
        int len = group.size();
        int MOD = (int)1e9 + 7; // 题目要求
        // int m = profit.size();
        // 前i个项目中,需要j个人,至少利润为k
        vector<vector<vector<int>>> dp(len+1, vector<vector<int>>(n+1, vector<int>(minProfit+1)));
        dp[0][0][0] = 1;
        for(int i = 1; i <= len; i++){
            int earn = profit[i - 1];
            int members = group[i - 1];
            for(int j = 0; j <= n; j++){
                for(int k = 0; k <= minProfit; k++){
                    dp[i][j][k] = dp[i - 1][j][k];
                    if(j >= members){
                        if(k<= earn)
                            dp[i][j][k] = (dp[i - 1][j][k] + dp[i - 1][j - members][0])%MOD;
                        else
                            dp[i][j][k] = (dp[i - 1][j][k] + dp[i - 1][j - members][k-earn])%MOD;            
                    }
                }
            }
        }
        int sum = 0;
        for(int i = 0; i <= n; i++){
            sum = (dp[len][i][minProfit] + sum)% MOD;
            /* 测试样例:
                10
                5
                [2,3,5]
                [6,7,8]
            */
            // cout << dp[len][i][minProfit]; dp[10][i][5]
            // 0 0 1 1 0 2 0 1 1 0 1
            // 相当于需要的i个人必须全部用上,否则计划数是0的。
        }
        return sum;
    }
};

70. 爬楼梯

// dp[i] = dp[i -1] + dp[i - 2];
// 每一层的方法等于前一层的方法+前面2层的方法
// dp[3] : 1+1+1 , 1+2, 2+1。 3种
// dp[2] : 1+1 2;
// dp[1] : 1;
// ∴  dp[3] = dp[2] + dp[1]
class Solution {
public:
    int climbStairs(int n) {

        vector<int> dp(n+1);
        dp[0] = 1;
        dp[1] = 1;
        for(int i = 2; i <= n; i++){
            dp[i] = dp[i -1] + dp[i - 2];
        }
        return dp[n];
    }
};


// 如果是爬 1,2,5的话
// 状态转移为 dp[i] = dp[i-1] + dp[i-2] + dp[i-5]
        int steps[2] = {1,2,5};
        for (int i = 1; i <= n; i++){
            for (int j = 0; j < 3; j++){
                int step = steps[j];
                if ( i < step ) continue;// 台阶少于跨越的步数
                DP[i] = DP[i] + DP[i-step];
            }
        }

518. 零钱兑换 II

class Solution {
public:
    int change(int amount, vector<int>& coins) {
        vector<int> dp(amount + 1);
        dp[0] = 1;
        for (int& coin : coins) {
            for (int i = coin; i <= amount; i++) {
                dp[i] += dp[i - coin];
            }
        }
        return dp[amount];
    }
};


class Solution {
public:
    int change(int amount, vector<int>& coins) {
        int K = coins.size() + 1;
        int I = amount + 1;
        int DP[K][I];

        //初始化基本状态
        for (int k = 0; k < coins.size() + 1; k++){
            DP[k][0] = 1;
        }
        for (int k = 1; k <= coins.size() ; k++){
            for (int i = 1; i <= amount; i++){  
                if ( i >= coins[k-1]) {
                    DP[k][i] = DP[k][i-coins[k-1]] + DP[k-1][i]; 
                } else{
                    DP[k][i] = DP[k-1][k];
                }
            }
        }
        return DP[coins.size()][amount];
    }
};
/*
        dp[2] = dp[2] + dp[2-2] = 1 + 1 = 2
        dp[3] = dp[3] + dp[3-2] = 1 + 1 = 2
        dp[4] = dp[4] + dp[4-2] 
        dp[10] = dp[10] + dp[10 - 5] = 6 + 4
        dp[5] = dp[5] + dp[0] = 3 + 1 = 4
        */

279. 完全平方数

class Solution {
public:
    // 判断是否为完全平方数
    bool isPerfectSquare(int x) {
        int y = sqrt(x);
        return y * y == x;
    }

    // 判断是否能表示为 4^k*(8m+7)
    bool checkAnswer4(int x) {
        while (x % 4 == 0) {
            x /= 4;
        }
        return x % 8 == 7;
    }

    int numSquares(int n) {
        if (isPerfectSquare(n)) {
            return 1;
        }
        if (checkAnswer4(n)) {
            return 4;
        }
        for (int i = 1; i * i <= n; i++) {
            int j = n - i * i;
            if (isPerfectSquare(j)) {
                return 2;
            }
        }
        return 3;
    }
};




// dp[i]理解为 数i的最小完全平方个数。
class Solution {
public:
    int numSquares(int n) {

        vector<int> dp(n+1);

        for(int i = 1; i <= n; i++){
            dp[i] = i; //max
            for(int j = 1; i - j*j  >= 0; j++){
                dp[i] = min(dp[i], dp[i - j*j] + 1); // +1 等价于dp[j*j]但是dp[j*j]是完全平方数也就是1
                cout<< i <<" "<< dp[i] << "    ";
            }
            cout<<endl;
        }

        return dp[n];
    }
};

278. 第一个错误的版本

难度简单317收藏分享切换为英文接收动态反馈

// The API isBadVersion is defined for you.
// bool isBadVersion(int version);

class Solution {
public:
    int firstBadVersion(int n) {
        int left = 1, right = n;
        int  mid = 0;
        while(left < right){

            // mid = (left + right)/2;
            mid = left + (right - left)/2;
            if(isBadVersion(mid)){
                right = mid; 
            }else{ //没错
                left = mid  + 1;
            }
        }
        return left;
    }
};

374. 猜数字大小

/** 
 * Forward declaration of guess API.
 * @param  num   your guess
 * @return 	     -1 if num is lower than the guess number
 *			      1 if num is higher than the guess number
 *               otherwise return 0
 * int guess(int num);
 */

class Solution {
public:
    int guessNumber(int n) {
        int left = 0, right = n;
        int mid = 0;

        while(left < right){
            mid = left + (right - left)/2;
            cout << guess(0);
            if(guess(mid) == -1){ // 大于
                right = mid -1;
            }else if(guess(mid) == 1){ // 小于
                left = mid + 1;
            }else if(guess(mid) == 0){
                return mid;
            }
        }
        
        return left;
    }
};
/*
10 6
5 5<6
left = 5 +  1
6 10 
8 8>6
right = 8 - 1 = 7
6 7  
6 6==6
*/

852. 山脉数组的峰顶索引


class Solution {
public:
    int peakIndexInMountainArray(vector<int>& arr) {
        int left = 1, right = arr.size();
        int ans;
        // 山脉数组只需要判断 arr[i] > arr[i+1]就可以, 因为这种情况就满足了arr[i]>arr[i+1]
        // for(int i = 1; i < arr.size(); i++){
        //     if(arr[i] > arr[i + 1]){
        //         ans =  i;
        //         break;
        //     }

        // }
        // return ans;

        while(left < right){
            int mid = left + (right - left)/2;
            
            // if(arr[mid] > arr[mid - 1] && arr[mid] > arr[mid + 1]){
            //     left = mid;
            //     break;
            // }else if(arr[mid] > arr[mid - 1]){
            //     left = mid + 1;
            // }else if(arr[mid] > arr[mid + 1]){
            //     right = mid - 1;
            // }

            if(arr[mid] > arr[mid + 1]){
                ans = mid;
                right = mid;
            }else{
                left = mid + 1;
            }
            
        } 
        return ans;
    }
};

877. 石子游戏

class Solution {
public:
    bool stoneGame(vector<int>& piles) {
        int length = piles.size();
        vector<vector<int>> dp(length, vector<int>(length));
        // i和j表示当前的石子堆的数量是j-i, 并且是从i到j的石子堆,dp[i][j]表示i到j中2个玩家拥有石子的最大差值
        for(int i = 0; i <length; i++){
            dp[i][i] = piles[i];
        }

        for(int i = length - 2; i >=0; i--){
            for(int j = i + 1; j <length; j++){
                dp[i][j] = max(piles[i] + dp[i+1][j], piles[j] + dp[i][j-1]); // max是因为对方也要取最大值
            }

        }

        return dp[0][length-1] > 0;

    }
};

65. 有效数字

class Solution {
public:
    bool hasE, hasNum, isFloat; 
    bool isNumber(string& s) {
        for(int i = 0; i < s.size(); i++) {
            char c = s[i];
            // 符号位只能在首位或E的后一位
            if((c == '-' || c == '+') && (i == 0 || s[i - 1] == 'e' || s[i - 1] == 'E')) {
                
            }else if((c == 'e' || c == 'E') && !hasE && hasNum) {
            //只存在一个E, 前面必须有数字, 后面也必须有数字
                hasE = true;
                hasNum = false;
            }else if(c == '.' && !isFloat && !hasE) {
            //只存在一个小数点, 不能在E的后面
                isFloat = true;
            }else if(isdigit(c)) {
                hasNum = true;
            }else {
                return false;
            }
        }
        return hasNum; // flase: '.'
    }
};

1239. 串联字符串的最大长度 位运算

// 迭代
class Solution {
public:
    int maxLength(vector<string>& arr) {
        int ans = 0;
        vector<int> masks={0};

        for(string &str: arr){
            int mask = 0;
            // 位运算
            // 用一个二进制数来表示该字符串的字符集合,二进制的第 ii 位为 11 表示字符集合中含有第 ii 个小写字母,为 00 表示字符集合中不含有第 ii 个小写字母。
            // 
            for(char ch: str){
                ch = ch - 'a';
                if((mask >> ch) & 1){ // 去重
                    mask = 0;
                    break;
                }
                mask = mask | 1 << ch; // 再第i位加入当前的字母
            }
            if(mask == 0){
                continue;
            }

            int n = masks.size();
            for(int i = 0; i < n; i++){
                int tmp = masks[i];
                if((tmp & mask) == 0){
                    masks.push_back( tmp | mask);
                    ans = max(ans, __builtin_popcount((tmp | mask)));
                }
                
            }            
        }
        return ans;
    }
};



// 回溯

class Solution {
private:
    void dfs(vector<int>& masks,int pos,int mask,int& ans)
    {
        if(pos==masks.size())
        {
            ans=max(ans,__builtin_popcount(mask));//__builtin_popcount()可以用于计算一个 32 位无符号整数有多少个位为1
            return;
        }
        //对于每个字符串都考虑 不选 和 选 两种情况
        //不选
        dfs(masks,pos+1,mask,ans);
        //选
        //要选取的话需要首先满足无公共元素
        if((mask&masks[pos])==0)//如果无公共元素
        {
            dfs(masks,pos+1,mask|masks[pos],ans);//如果要选取的话,则把对应的字符加上,即对应二进制位赋予1
        }
    }
public:
    int maxLength(vector<string>& arr) 
    {
        vector<int> masks;
        for(auto str:arr)
        {
            int mask=0;//二进制从右向左起,分别对应a,b,c,d... ...
            // eg. a: 1 b: 01 c: 100 d: 1000 abc: 111
            for(auto ch:str)
            {
                ch-='a';//获取当前字符ch从右向左位于二进制的第几个位置
                if((mask>>ch)&1)//mask>>ch获取了mask中该位置上是0还是1。如果是1代表该字符已存在
                {
                    mask=0;//则该字符串自身就包含了重复字符,不保留
                    break;
                }
                //如果该字符没有重复,则给对应的二进制位赋予1
                mask|=1<<ch;
            }
            if(mask)//如果字符串不等于0,即没有重复字符
            {
                masks.push_back(mask);
            }
        }
        int ans=0;
        dfs(masks,0,0,ans);
        return ans;
    }
};

1600. 皇位继承顺序

// 这篇算法学到了c++中 成员变量, 字典map<string, vector<string>> tree>, 集合set, 以及最后的迭代器的使用,find

class ThroneInheritance {
public:

    string king; // 全局变量
    unordered_map<string, vector<string>> tree; // dfs tree
    unordered_set<string> dead;
    ThroneInheritance(string kingName) {
        king = kingName;

    }
    
    void birth(string parentName, string childName) {
        tree[parentName].push_back(childName); // child value  parent key


    }
    
    void death(string name) {
        dead.insert(name);
    }
    

    void dfs(vector<string>& ans, string parentName){ // 注意形参的vector<string>&ans的引用符,否则无法更新。

        if(dead.find(parentName) == dead.end()){// find没找到,返回end()
            ans.push_back(parentName);
        } 

        for(auto i = tree[parentName].begin(); i != tree[parentName].end(); i++){
            dfs(ans, *i); // 必须是*i 类似指针
        }

    }
    vector<string> getInheritanceOrder() {

        vector<string> ans;
        dfs(ans, king);
        return ans;

    }
};

401. 二进制手表

__builtin_popcount(num)  计算num的二进制中1的个数。
class Solution {
public:
    vector<string> readBinaryWatch(int turnedOn) {
        
        vector<string> ans;
        // o(720) 
        for(int i = 0; i < 12; i++){
            for(int j = 0; j < 60; j++){
                cout<<__builtin_popcount(i)<<" "<<__builtin_popcount(j)<<endl;
                if(__builtin_popcount(i) + __builtin_popcount(j) == turnedOn){
                    ans.push_back(to_string(i)+":"+(j<10? "0":"")+to_string(j));
                }
            }
        }
        return ans;
    }
};


// 二进制枚举 一共10个灯,有2^10=1024种灯
class Solution {
public:
    vector<string> readBinaryWatch(int turnedOn) {
        vector<string> ans;
        for (int i = 0; i < 1024; ++i) {
            int h = i >> 6, m = i & 63; // 用位运算取出高 4 位和低 6 位
         	// 1111 | 111111  前4位表示hour,后四位表示minute 因此要获取前4位需要>>操作,需要获取后6位用&操作。
            // 判断合理性
            if (h < 12 && m < 60 && __builtin_popcount(i) == turnedOn) {
                ans.push_back(to_string(h) + ":" + (m < 10 ? "0" : "") + to_string(m));
            }
        }
        return ans;
    }
};

剑指 Offer 38. 字符串的排列

class Solution {
public:
    vector<string> permutation(string s) {
        vector<string> ans;
        int pos = 0;
        dfs(ans, s, pos);
        return ans;
    }

    void dfs(vector<string> &ans, string &s, int pos){
        if(pos == s.size())
            ans.push_back(s);

        for(int i = pos; i < s.size(); i++){
            bool flag = true;
            for(int j = pos; j < i; j++){//剪枝 eg. 'aabc' 只有12个排列
                if(s[i] == s[j])
                    flag = false;
            }
            if(flag){
                swap(s[i], s[pos]);
                dfs(ans, s, pos + 1);
                swap(s[i], s[pos]);
            }
        }
    }
};
// pos = 0  i = 0, j = pos = 0, s[j] = s[i] flag = false, i = 1, j = pos = 0, s[j]!=s[i] if(flag) swap(s[0], s[1])
// abc --> bac dfs(pos+1) 
// pos = 1 i = 1, j = pos = 1




// 利用哈希表
class Solution {

public:
    unordered_map<char, int> m;
    vector<string> ans;
    vector<string> permutation(string s) {
        for(auto c:s){
            m[c]++;
        }
        int  n = s.size();
        dfs(n, "");
        return ans;
    }
    void dfs(int n, string s){
        if(n == 0){
            ans.push_back(s);
            return;
        }
        
        // 迭代器的使用
        unordered_map<char, int>::iterator t;
        for(t = m.begin(); t != m.end(); t++){ // 第一种
        // for(auto &t: m){ // 第二种
           
            /*
            if (t.second){
                t.second --;
                dfs(n-1, s+t.first);
                t.second ++;
            }
            */
            
            // 指针
            if(t->second){
                t->second--;
                dfs(n-1, s+t->first);
                t->second++;
            }
            
            /* 
            if((*t).second){
                (*t).second--;
                dfs(n-1, s+(*t).first);
                (*t).second++;
            }
            /*
        }
    }
};

剑指 Offer 15. 二进制中1的个数

class Solution {
public:
    int ans = 0;
    int hammingWeight(uint32_t n) {
        // int flag;
        // for(int i = 0; i < 32; i++){
        //     flag = n & (1<<i); // n和 2^i
        //     if(flag)
        //         ans++; 
        // }
        
        // 位运算 n = n & (n-1)
        // 110 --> 100  --> 000 --> ans = 3
        while(n){
            n = n&(n-1);
            ans++;
        }
        return ans;

    }
};

// 1000001


// 0000001
// 0000010
// 0000100
// 0001000
// 0010000
// 0100000
// 1000000

149. 直线上最多的点数

最后我们再加四个小优化:

  • 在点的总数量小于等于 22 的情况下,我们总可以用一条直线将所有点串联,此时我们直接返回点的总数量即可;
  • 当我们枚举到点 i 时,我们只需要考虑编号大于 i 的点到点 i 的斜率,因为如果直线同时经过编号小于点 i 的点j,那么当我们枚举到 j时就已经考虑过该直线了;
  • 当我们找到一条直线经过了图中超过半数的点时,我们即可以确定该直线即为经过最多点的直线;
  • 当我们枚举到点 ii(假设编号从 00 开始)时,我们至多只能找到 n − i n-i ni个点共线。假设此前找到的共线的点的数量的最大值为 kk,如果有 k ≥ n − i k \geq n-i kni,那么此时我们即可停止枚举,因为不可能再找到更大的答案了。
// 暴力解法
// 找出2个点, 然后找出第三个点, 计算3点之间的斜率,因为4点可以平行,三点如果斜率相等只有可能共线
class Solution {
public:

    int gcd(int a,  int b){
        if(b == 1){
            return gcd(b, a%b);
        }
        return a;
    }
    int maxPoints(vector<vector<int>>& points) {

        int n = points.size();
        int ans = 1;
        for(int i = 0; i < n; i++){
            vector<int> num1 = points[i];
            for(int j = i+1; j < n; j++){
                vector<int> num2 = points[j];
                int cnt = 2;
                for(int k = j+1; k < n; k++){
                    vector<int> num3 = points[k];

                    int s1 = (num2[1] - num1[1]) * (num3[0] - num2[0]);
                    int s2 = (num3[1] - num2[1]) * (num2[0] - num1[0]);
                    if(s1 == s2)
                        cnt++;
                }
                ans = max(ans, cnt);
                if(ans > n / 2) return ans; // 当我们找到一条直线经过了图中超过半数的点时,我们即可以确定该直线即为经过最多点的直线;
            }
        }
        return ans;
    }
};
// 官方优化
// 
// unordered_map<int, int> m;
// unordered_map<string, int> m;
class Solution {
public:
    // gcd(0, 25) = 25  因此dy = 25 dx = 0 --> dy = 1, dx = 0
    int gcd(int a, int b) {
        return b ? gcd(b, a % b) : a;
        // return b==0 ? a: gcd(b, a%b);
    }

    int maxPoints(vector<vector<int>>& points) {
        int n = points.size();
        if (n <= 2) {
            return n;
        }
        int ret = 0;
        for(int i =0; i < n; i++){
            if(ret >= n - i|| ret > n/2)
                return ret;
            
            // unordered_map<int, int> m;
            unordered_map<string, int> m;
            for(int j = i + 1; j < n; j++){

                int x = points[i][0] - points[j][0];
                int y = points[i][1] - points[j][1];
                if(x == 0){ // 为了在map中存储在一样的位置
                    y = 1;
                }else if(y == 0){ // 为了在map中存储在一样的位置
                    x = 1;
                }else if(y<0){ // 为了在map中存储在一样的位置
                    x = -x;
                    y = -y;
                }
                int g = gcd(abs(x), abs(y));
                x = x / g, y = y / g;
                string s = to_string(x)+"_"+to_string(y);
                // cout << s;
                // m[y + (20000+1)*x]++;
                m[s]++;
            }
            for(auto &s: m){
                ret = max(ret, s.second+1);
            }
        }
    return ret;

    }
};

1 -2  -1 2
    
   

// 如果用string的方法来存储, 就简便很多 不用考虑那么多
class Solution {
public:
    int gcd(int a, int b) {
        return b ? gcd(b, a % b) : a;
    }

    int maxPoints(vector<vector<int>>& points) {
        int n = points.size();
        if (n <= 2) {
            return n;
        }
        int ret = 0;
        for(int i =0; i < n; i++){
            if(ret >= n - i|| ret > n/2)
                return ret;
            
            // unordered_map<int, int> m;
            unordered_map<string, int> m;
            for(int j = i + 1; j < n; j++){

                int x = points[i][0] - points[j][0];
                int y = points[i][1] - points[j][1];
                /*
                if(x == 0){ // 为了在map中存储在一样的位置
                    y = 1;
                }else if(y == 0){ // 为了在map中存储在一样的位置
                    x = 1;
                }else if(y<0){ // 为了在map中存储在一样的位置
                    x = -x;
                    y = -y;
                }
                */
                int g = gcd(x, y);
                x = x / g, y = y / g;
                string s = to_string(x)+"_"+to_string(y);
                // cout << s;
                // m[y + (20000+1)*x]++;
                m[s]++;
            }
            for(auto &s: m){
                ret = max(ret, s.second+1);
            }
        }
    return ret;

    }
};

752. 打开转盘锁(BFS)

image-20210625122247215

做了很久,要点有:多维vector的赋值。

BFS的思路。

char a = 'a';
a = a + 2 # 'c'

a - 'a' # 2
'1' - '0'  # 1

'1' + 1 # '2'
// temp[i] = '1';
// cout<<'1' - '0' << endl;
// cout<<temp[i]<<endl;
// cout<< temp[i] + 1<<endl;
// cout<< temp[i] + '1'<<endl;
// cout<<temp[i] - '1'<<endl;
// cout<<temp[i] + 1 - '0'<< endl;
// cout<<temp[i] + '1' - '0'<< endl;
// 相比较于下一题, 我这样子的思路不太好
// 最好还是 q.empty   q.size()  然后遍历q的节点这样
class Solution {
public:
    int openLock(vector<string>& deadends, string target) {
        //  vector<int> ans(10, 0);  10 rows, value of 0
        // vector<vector<int>> ans(10, vector<int>(10));

        if(target == "0000")
            return 0;
        // 多维vector的赋值 千万不要写错
        vector<vector<vector<vector<bool>>>> visited(10, vector<vector<vector<bool>>>(10, vector<vector<bool>>(10, vector<bool>(10, false)))); // bool[10][10][10][10] represents 0000~ 9999 
        
        for(auto  &str: deadends){
            if(str == "0000")
                return -1;       
            visited[str[0]-'0'][str[1]-'0'][str[2]-'0'][str[3]-'0'] = true;
        }

        queue<string> q;
        q.push("0000"); // init
        visited[0][0][0][0] = true;
        int len_queue = 1;
        int ans = 0;
        // bfs
        while(!q.empty()){
            // ans
            if(q.front() == target){
                // ans++;
                break;
            }
            string temp;
            
            for(int i = 0; i < target.size(); i++){
                // add
                // eg. 0000 --> 1000; 9000 --> 0000
                temp = q.front();
                if(temp[i] == '9')
                    temp[i] = '0';
                else
                    temp[i] = temp[i] + 1;
                    
                if(!visited[temp[0] - '0'][temp[1] - '0'][temp[2] - '0'][temp[3] - '0']){
                    q.push(temp);
                    visited[temp[0] - '0'][temp[1] - '0'][temp[2] - '0'][temp[3] - '0'] = true;
                }

                // substract
                // eg. 0000 --> 9000; 9000 -> 8000
                // need to redirect
                temp = q.front();
                if(temp[i] == '0')
                    temp[i] = '9';
                else   
                    temp[i] = temp[i] - 1;
                if(!visited[temp[0] - '0'][temp[1] - '0'][temp[2] - '0'][temp[3] - '0']){
                    q.push(temp);         
                    visited[temp[0] - '0'][temp[1] - '0'][temp[2] - '0'][temp[3] - '0'] = true;
                }
            }
            
            q.pop();
            len_queue--;
            if(len_queue == 0){
                len_queue = q.size();
                ans++;
            }

        }
        if(q.empty())
            return -1;
        return ans;
    }
};

773. 滑动谜题(BFS)

BFS 问题

while(!q.empty())
	while(q.size()--){
		if q.front() ==  ans
			return cnt;
		// first visited
		if set.count(q.front()){
			q.pop()
			continue
		}else{
			set.insert(q.front)
		}
		for(int i = 0; i < node.size(); i++)
		// then visited
			tmp = q.front do some opeartion
			if(set.count(tmp))
				continue
			else
				q.push(temp)
		q.pop()
		
	}
class Solution {
public:
    int slidingPuzzle(vector<vector<int>>& board) {

        vector<vector<int>> neighbours = {{1, 3}, {0, 2, 4}, {1,5}, {0, 4}, {1, 3, 5}, {2, 4}};
        // 优化 queue里面的每一个元素为 string
        //queue<vector<vector<int>>> q;
        queue<string> q;
        unordered_set<string> set; // 用set来过滤已经出现的情况(不满足,就不是最小次数)

        string b;
        for(int i = 0; i < board.size(); i++){
            for(int j = 0; j < board[0].size(); j++){
                b += board[i][j] + '0';
            }
        }


        int ans = 0;
        q.push(b);
        while(!q.empty()){
            int n = q.size();
            
            for(int i = 0; i < n; i++){
                // 先放入q中 在去重
                // 或者可以在下面的for中先判断,不满足条件就不放入队列中
                if(q.front() == "123450"){
                    return ans;
                }

                // 去重方案1
                // if(set.count(q.front())){
                //     q.pop();
                //     continue;
                // }else{
                //     set.insert(q.front());
                // }
                int pos = q.front().find("0");
                for(auto &i : neighbours[pos]){
                    string temp = q.front();
                    swap(temp[pos], temp[i]);
                    // 去重方案2
                    if(set.count(temp)){
                        
                        continue;
                    }else{
                        set.insert(temp);
                    }
                    q.push(temp);
                }
                q.pop();

            }
            ans++;

        }

        if(q.empty())
            return -1;

        return ans;
        
    }
};


5797. 两个数对之间的最大乘积差(sort)

class Solution {
public:
    static bool compare(int a, int b){
        return a > b;
    }
    int maxProductDifference(vector<int>& nums) {
        
        sort(nums.begin(), nums.end(), compare);        
        return (nums[0] * nums[1]) - (nums[nums.size()-1] * nums[nums.size()-2]);
    }
};

// 5 6 2 7 4
// mx1 mx2 
// 6 5
// mn1 mn2
// 5 6 


// for 2 7 4  
// 6 5 
// 2 5

// 7 6
// 2 5

// 7 6 
// 2 4

815. 公交路线

(认真严肃!!!int n = q.size())

别给我省下这一步:!!! 不要眼高手低 觉得浪费时间

        while(!q.empty()){
            int n = q.size(); // 要想正序排列  必须先存储!!!!因为在后面的for循环中有q.pop()这个操作,如果你是i<q.size() 那么size会随着pop()操作变化。
            
            for(int i = 0; i < n; i++){
			// 逆序直接写
            for(int i = q.size()-1; i>=0; i--)
// 这题的bfs 中, 多一个for 循环 并且set去重 以及 return 判断target 是否和当前队列头元素相等的操作 也不太一样。 需要更加理解题目 套公式

//  需要创建一个map优化  map[i] = {j,....} 表示  车站i 所在的公交线路有j,...
// 因为是判断最少公交线路, 因此去重去的是route.size()的值 也就是有多少线路,最大不超过route.size()
class Solution {
public:
    int numBusesToDestination(vector<vector<int>>& routes, int source, int target) {
        if(source == target)
            return 0;
        queue<int> q;
        int ans = 1;
        q.push(source);
        unordered_map<int, vector<int>> m;
        unordered_set<int> set;
        for(int i = 0; i < routes.size(); i++){
            for(auto &j : routes[i]){
                m[j].push_back(i);
            }
        }


        while(!q.empty()){
            int n = q.size();
            for(int i = 0; i < n; i++){
                int frontStation = q.front();
                              
                for(auto &routeIndex: m[frontStation]){

                    if(set.count(routeIndex)){
                         continue;
                    }else{
                        set.insert(routeIndex);
                        for(const auto &station: routes[routeIndex]){
                            if(station == target){
                                return ans;
                            }
                            q.push(station);
                        }
                    }
                }  
                q.pop();  
            }
            ans++;
        }

        return -1;
    }
};

168. Excel表列名称

虽然是简单题,但是我还是遇到了2个坑,首先是char 和string拼接的问题。使用+=or push_back()

y += d;

In gcc, basic_string::operator+= is just a call in push_back
     
std::string y("Hello world");
y.push_back('d')
std::cout << y;

另外这2个方法涉及自动强制转换int–> char。

string ans="";
cout<<2+'A'-1<<endl;  // 66 不是我们需要的答案

// 使用+= 操作相当于 强制转换了。
cout<< (char)(2+'A'-1)<<endl; // B
ans += 2 + 'A' - 1; // B


// 使用push_back
string ans="";
ans.push_back(2+'A'-1);
ans.push_back(2+'A'-1);
cout << ans; // "AA"

对于10进制转为X进制的方法:

while(num!=0){
	temp = num % X; // 得到余数
	num = num / X; // 得到除数
}

这题比较特殊,虽然是26进制转换,本来是26—》10;但是它要求在26的时候等于Z。

//一般性的进制转换题目无须进行额外操作,是因为我们是在「每一位数值范围在 [0,x)的前提下进行「逢 x 进一」。
//本题需要我们将从 1 开始,因此在执行「进制转换」操作前,我们需要先对 columnNumbercolumnNumber 执行减一操作,从而实现整体偏移。
class Solution {
public:
    string convertToTitle(int columnNumber) {
        string ans = "";        
        while(columnNumber != 0){
            columnNumber--;
            int temp = (columnNumber) % 26;
            ans += temp + 'A';

            columnNumber = (columnNumber) / 26;
            
        }

        // string res;
        // for(int i = ans.size()-1; i >= 0; i--){
        //        res.push_back(ans[i]);
        // }
        reverse(ans.begin(), ans.end()); // 翻转方法
        return ans;
        
    }

};

剑指 Offer 37. 序列化二叉树

codec.deserialize(codec.serialize(root));
这段代码的意思就是其实里面是你自己设计,但是你要自圆其说,保证 encoder-decoder后的结果一样
你可以是1,2,X,X,3,4,5
也可以是1,2,None,None,3,4,5
也可以是1,2,3,X,X,4,5,
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Codec {
public:

    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        
    }
};

// Your Codec object will be instantiated and called as such:
// Codec codec;
// codec.deserialize(codec.serialize(root));



class Codec {
public:
    // 先序遍历
    void rserialize(TreeNode* root, string& str) {
        if (root == nullptr) {
            str += "null,";
        } else {
            // to_string
            str += to_string(root->val) + ",";
            rserialize(root->left, str);
            rserialize(root->right, str);
        }
    }

    string serialize(TreeNode* root) {
        string ret;
        rserialize(root, ret);
        return ret;
    }

    TreeNode* rdeserialize(list<string>& dataArray) {
        if (dataArray.front() == "null") {
            dataArray.erase(dataArray.begin()); //删除保证 下一次取到新的元素
            return nullptr;
        }
		// stoi
        TreeNode* root = new TreeNode(stoi(dataArray.front()));
        dataArray.erase(dataArray.begin()); //删除保证 下一次取到新的元素
        // 依次遍历 左右子树
        root->left = rdeserialize(dataArray);
        root->right = rdeserialize(dataArray);
        return root;
    }
	// list<strig> 
    TreeNode* deserialize(string data) {
        list<string> dataArray;
        string str;
        
        for (auto& ch : data) {
            if (ch == ',') { //split
                dataArray.push_back(str);
                str.clear();
            } else {
                str.push_back(ch);
            }
        }
        // for(auto &ls: dataArray)
        //     cout<<ls;
        
        // if (!str.empty()) {
        //     dataArray.push_back(str);
        //     str.clear();
        // }
        return rdeserialize(dataArray);
    }
};

LCP 07. 传递信息 (邻接矩阵)

本题的关键在于创建数据结构 图中的邻接矩阵,对于NxN的relation,可以用vector控制每一个结点的x条边。(就不用提前设置好nxn的矩阵。

// BFS
// 队列中示例
// 0    1      2            3
// 0, 2, 4,  1, 3, 0,   4, 4, 2, 4
class Solution {
public:
    int numWays(int n, vector<vector<int>>& relation, int k) {
        // 邻接矩阵
        
        vector<vector<int>> edges(n); // vector<vector<int>> edges(n, vector<int>(n))
        for(auto &edge : relation){
            int x = edge[0], y = edge[1]; // x --> y
            edges[x].push_back(y);
        }

        queue<int> q;
        q.push(0);

        int ans = 0;
        int step = 0;
        
        // 需要设置一个step来控制循环时间
        while(!q.empty() && step < k){
            step++;
            int n  = q.size();
            for(int i = 0; i < n; i++){
                int temp = q.front();
                q.pop();
                // 与q.front()有边的结点入队
                for(auto &node: edges[temp]){
                    q.push(node);
                }
            }
        }
        
        // 
        while(!q.empty()){
            int temp = q.front();
            q.pop();
            if(temp == n-1)
                ans++;
        }


        return ans;
    }
};'
    
    
 // dfs
    
    
class Solution {
public:
    int ans = 0;
    int step = 0;
    
    int numWays(int n, vector<vector<int>>& relation, int k) {
        // 邻接矩阵
        vector<vector<int>> edges(n);
        for(auto &edge : relation){
            int x = edge[0], y = edge[1]; // x --> y
            edges[x].push_back(y);
        }
        dfs(0, 0, edges, k, n);
        
        return ans;

        
    }


    void dfs(int index, int step, vector<vector<int>>  &edges, int k, int n){
        if(step == k){
            if(index == n-1){
                ans++;
            }
            return;
        }
        for(auto &egde: edges[index])
            dfs(egde, step+1, edges, k, n);
    }
};

451. 根据字符出现频率排序(pair 排序)

// map 不能直接使用sort函数
// 需要先把 map 的元素存成pair 
class Solution {
public:
    static bool compare(pair<char, int> a, pair<char, int> b){
        return a.second > b.second;
    }
    string frequencySort(string s) {

        map<char, int> m;
        vector<pair<char, int>> v; // pair元素的vector
        for(auto &str: s){
            m[str]++;
        }
        for(auto &it: m){ // it 就是 pair<char, int> 因此可以直接输入
            v.push_back(it);
        }
        
        sort(v.begin(), v.end(), compare);  
        string ans = "";
        for(int i = 0; i < v.size(); i++){

            for(int j = 0; j < v[i].second; j++)
                ans.push_back(v[i].first);
        }
        return ans;

    }
};

645. 错误的集合

数学方法,求1+2...+N的和,nums唯一set()的和,和nums的和对应做减法直接得到结果
class Solution:
    def findErrorNums(self, nums: List[int]) -> List[int]:
        S = sum(set(nums))
        return [sum(nums)-S ,len(nums)*(len(nums)+1)//2-S]

class Solution {
public:
    vector<int> findErrorNums(vector<int>& nums) {
        vector<int> rec(nums.size() + 1);
        for(auto &num: nums){
            rec[num]++;
        }

        vector<int> ans;
        int copy_num = -1;
        int left_num = -1;
        bool flag_copy = false;
        bool flag_left = false;
        for(int i = 1; i < nums.size() + 1; i++){
            if(flag_copy && flag_left)
                break;
            
            if(rec[i] > 1){
                copy_num = i;
                flag_copy = true;
            }
            if(left && rec[i] ==0){
                left_num = i;
                flag_left = true;
            }


        }
        ans.push_back(copy_num);
        ans.push_back(left_num);
        return ans;
                
        
    }
};

1418. 点菜展示表

class Solution {
public:
    vector<vector<string>> displayTable(vector<vector<string>>& orders) {
        unordered_map<int, unordered_map<string, int>> foodNum;
        // map <int, string> 3: (x:0 y:1 z:2)
        
        unordered_set<string> foodSet;
        
        for(auto &order: orders){
            foodSet.insert(order[2]);
            foodNum[stoi(order[1])][order[2]]++;
        }
        //  sort_food
        vector<string> sort_food;
        for(auto &food: foodSet){
            sort_food.push_back(food);
        }
        sort(sort_food.begin(), sort_food.end());

        //  sort_table
        vector<int> sort_table;  
        for(auto &table: foodNum){
            sort_table.push_back(table.first);
        }
        sort(sort_table.begin(), sort_table.end()); 


        vector<vector<string>> ans(sort_table.size() + 1);
        ans[0].push_back("Table");
        
        // row - table
        for(int i = 1; i < sort_table.size() + 1; i++){
            ans[i].push_back(to_string(sort_table[i - 1])); 
            // cout << to_string(sort_table[i - 1]) << endl;
        }
        
        // column - food 
        for(int i = 1; i < sort_food.size() + 1; i++){
            ans[0].push_back(sort_food[i - 1]);
            // cout << sort_food[i - 1] << endl;
            
        }
        // cout << foodNum[sort_table[0]][sort_food[3]];
        for(int i = 1; i < sort_table.size() + 1; i++){
            unordered_map<string, int> each_table = foodNum[sort_table[i - 1]];
            for(int j = 1; j < sort_food.size() + 1; j++){
                // ans[i].push_back(sort_food[j - 1]);
                string each_table_food = sort_food[j - 1];
                string each_food_num = to_string(each_table[each_table_food]);
                ans[i].push_back(each_food_num);
                
            }
        }

        return ans;
    }
};

1711. 大餐计数

class Solution {
public:
    static constexpr int MOD = 1'000'000'007;

    int countPairs(vector<int>& deliciousness) {
        int maxVal = *max_element(deliciousness.begin(), deliciousness.end());
        int maxSum = maxVal * 2;
        int pairs = 0;
        unordered_map<int, int> mp;
        int n = deliciousness.size();
        for (auto& val : deliciousness) {
            for (int sum = 1; sum <= maxSum; sum <<= 1) {
                int count = mp.count(sum - val) ? mp[sum - val] : 0;

                pairs = (pairs + count) % MOD;
            }

            mp[val]++;
        }
        return pairs;
    }
};

面试题 17.10. 主要元素

// 朴素解法  max_element的使用 利用map.value 取最大值,需要做一个compare自定义函数.
class Solution {
public:
    static bool compare(pair<int, int> num1, pair<int, int> num2){
        return num1.second < num2.second;
    }
    int majorityElement(vector<int>& nums) {
        unordered_map<int, int> mp;
        for(int i = 0; i < nums.size(); i++){
            mp[nums[i]]++;
        }
        // 1 1 4 2
        vector<pair<int, int>> v;
        pair<int ,int> maxval = *max_element(mp.begin(), mp.end(), compare);
        
        
        if(maxval.second > nums.size()/2)
            return maxval.first;

        return -1;
    }
};


// 朴素解法
class Solution {
public:
    int majorityElement(vector<int>& nums) {
        unordered_map<int, int> mp;
        for(int i = 0; i < nums.size(); i++){
            mp[nums[i]]++;
            if(mp[nums[i]] * 2 > nums.size())
                return nums[i];
        }
        return -1;

    }
};


// 摩尔投票
class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int candidate = -1;
        int count = 0;
        for (int& num : nums) {
            if (count == 0) {  // count = 0 加入新元素
                candidate = num;
            }
            if (num == candidate) { // 比较每次的元素和候选元素是否相等
                count++; // 相等则 count++
            } else {
                count--; // 否则 count--
            }
        }
        count = 0;
        int length = nums.size();
        for (int& num : nums) {  // 遍历所有元素,找到等于候选元素的个数
            if (num == candidate) {
                count++;
            }
        }
        return count * 2 > length ? candidate : -1;  // 如果count*2 大于数组长度则表明找到元素。
    }
}; 
// 2 2 1 1 1 2 2 
// num = 2  count == 0  cand = 2  cout++
// num = 2  cand = num  count++ = 2
// num = 1 count!=0  cand != num cout-- = 1
// num = 1 count!=0  cout-- = 0
// num = 1  count == 0 cand =  num = 1 cout++
// num = 2 count!=0 cand!=num cout-- = 0
// num = 2 count == 0 cand = num = 2 cout++
// for(num : nums)
//      if num == cand
            cout_final++
// return cou_final * 2 > size()? candidate:-1;





//  1 2 5 9 5 5 5 
//  5
//  candidiate = 1 num = 1  count++ = 1
//  num = 2  num !=candidate count-- = 0
//  num = 5  count = 0 candidata = 5   count++ = 1
//  num = 9 count!=0 num!=candidate cout-- = 0
//  num = 5 count == 0  candidata = num = 9 cout++
//  num = 5 count!= 0  num == candidite = 5 cout++
//  count++ = 3

H 指数 II

class Solution {
public:
    int hIndex(vector<int>& citations) {
        
        for(int i = 0; i < citations.size(); i++){
            int h  = citations.size() - i; 
            if(citations[i] >= h){
                return h;
            }
        }

        return 0;
        
        

    }
};



// 二分
class Solution {
public:
    int hIndex(vector<int>& citations) {
        
        // for(int i = 0; i < citations.size(); i++){
        //     int h  = citations.size() - i; 
        //     if(citations[i] >= h){
        //         return h;
        //     }
        // }

        // return 0;

        int n = citations.size();
        int left = 0, right = n - 1;
        while(left <= right){
            int mid = left + (right - left) / 2;  

            if(citations[mid] >= citations.size() - mid){ // 
                right = mid - 1;
            }else{
                 // 2  2 + 2 = 4
                left = mid + 1;
            }

        }
        return n- left;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值