2022.01.26刷题
1122. 数组的相对排序
题解: 自定义排序
vector<int> relativeSortArray(vector<int>& arr1, vector<int>& arr2) {
    unordered_map<int, int> rank;
    for (int i = 0; i < arr2.size(); ++i) rank[arr2[i]] = i;
    sort(arr1.begin(), arr1.end(), [&](int x, int y) {
        if (rank.count(x)) 
            return rank.count(y) ? rank[x] < rank[y] : true;
        else 
            return rank.count(y) ? false : x < y;
    });
    return arr1;
}
//自定义元组进行排序:
public:
    vector<int> relativeSortArray(vector<int>& arr1, vector<int>& arr2) {
        unordered_map<int, int> rank;
        for (int i = 0; i < arr2.size(); ++i) {
            rank[arr2[i]] = i;
        }
        auto mycmp = [&](int x) -> pair<int, int> {
            return rank.count(x) ? pair{0, rank[x]} : pair{1, x};
        };
        sort(arr1.begin(), arr1.end(), [&](int x, int y) {
            return mycmp(x) < mycmp(y);
        });
        return arr1;
    }
};
//自己: 模拟
vector<int> relativeSortArray(vector<int>& arr1, vector<int>& arr2) {
    unordered_map<int,int> um;
    for(auto i:arr1) um[i]++;
    vector<int> res;
    for(auto i:arr2){
        int n = um[i];
        while(n--)
            res.push_back(i);
        um.erase(i);
    }
    int n = res.size();
    for(auto [key,val]:um){
        for(int i = 0;i<val;i++){
            res.push_back(key); 
        }
    }
    sort(res.begin()+n,res.end());
    return res;
}
292. Nim 游戏
代码就一行: bool canWinNim(int n) {return n%4;}
其实还给了一个技巧, 就是说 我们可以看到: 不管>4是什么, 我作为后手总能给他搞到 4的倍数去.
canwin[1] = canwin[2] = canwin[3] = true; 
canwin[4-n] = !canwin[n-1] || !canwin[n-2] || !canwin[n-3]; 如果这三步都赢不了 就输了.
520. 检测大写字母
'a' > 'A'
'A' : 0100 0001
'a': 0110 0001
我自己模拟很容易出现模拟不清晰的情况.
还有尽量用 islower 和 isupper.
bool detectCapitalUse(string word) {
    // 若第 1 个字母为小写,则需额外判断第 2 个字母是否为小写
    if (word.size() >= 2 && islower(word[0]) && isupper(word[1])) {
        return false;
    }
    // 无论第 1 个字母是否大写,其他字母必须与第 2 个字母的大小写相同
    for (int i = 2; i < word.size(); ++i) {
        if (islower(word[i]) ^ islower(word[1])) {
            return false;
        }
    }
    return true;
}
作者:LeetCode-Solution
bool detectCapitalUse(string word) {
    if(word.size()==1) return true;
    bool capi = word[0]<'a';
    bool capi2= word[1]<'a';
    if(!capi && capi2) return false;
    for(int i = 2;i<word.size();i++){
        if(word[i]<'a') {
            if(!capi2 || !capi) return false;
        }else{
            if(capi2) return false;
        }
    }
    return true;
}
168. Excel表列名称
这个题有点绕... 不过因为是在[1,26]范围内 进行26进制转换的, 所以每次转换前先n--
string convertToTitle(int n) {
    string res = "";
    while(n){
        n--; // 这个很重要 要不然会出现 A@Y 等错误...
        res+= n%26+'A';
        n/=26;
    }
    reverse(res.begin(), res.end());
    return res;
}
1005. K 次取反后最大化的数组和
非常的绕..
int largestSumAfterKNegations(vector<int>& nums, int k) {
    sort(nums.begin(),nums.end());
    int neg = 0;
    for(int i = 0;i<nums.size();i++) if(nums[i]<0) neg++;
    for(int i = 0;i<k && i<neg;i++){
        nums[i] = -nums[i];
    } 
    int sum = accumulate(nums.begin(),nums.end(),0);
    if(k>neg && (k-neg)%2 == 1){
        sum -=  2*(*min_element(nums.begin(), nums.end()));
    }
    return sum;
}
459. 重复的子字符串
为什么成立呢? 如果重复, 一定可以通过移位和换行得来的. 这样子2倍的字符串, 一定包含了这些, 所以可行.
//KMP 做法, 非常的简洁 O(3n)
public boolean repeatedSubstringPattern(String s) {
    String str = s + s;
    return str.substring(1, str.length() - 1).contains(s);
}
1013. 将数组分成和相等的三个部分
模拟题, 记得最后是 return l+1<r 因为我们需要把整个区间分成3段.
1446. 连续字符
    int maxPower(string s) {
        char pre = 1; 
        int precnt = 0;
        int res = 1;
        // 寻找连续的常用代码...
        for(auto c:s){
            if(c==pre){
                precnt++;
                res = max(res,precnt);
            }else pre=c, precnt = 1;
        }
        return res; 
    }
1078. Bigram 分词
尽量自己实现一个python的.split(' ')函数吧..
vector<string> split(string s){
    vector<string> vs;
    int l = 0;
    for(int i = 0;i<s.size();i++){
        if(s[i] == ' '){
            vs.push_back(s.substr(l,i-l));
            l = i+1;
        }
    }
    if(l<s.size()) vs.push_back(s.substr(l,s.size()-l));
    return vs;
}
724. 寻找数组的中心下标
前缀和或者直接模拟
1360. 日期之间隔几天
这个模拟可真不容易..
private: // 多看一下...
	bool leap_year(int year) {
         return ((year % 400 == 0) || (year % 100 != 0 && year % 4 == 0));
    }
    int date_to_int(string date) {
        int year, month, day;
        sscanf(date.c_str(), "%d-%d-%d", &year, &month, &day);
        int month_length[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        int ans = day - 1;
        while (month != 0) {
            --month;
            ans += month_length[month];
            if (month == 2 && leap_year(year))
                ans += 1;
        }
        ans += 365 * (year - 1971);
        ans += (year - 1) / 4 - 1971 / 4;
        ans -= (year - 1) / 100 - 1971 / 100;
        ans += (year - 1) / 400 - 1971 / 400;
        return ans;
    }
public:
    int daysBetweenDates(string date1, string date2) {
        return abs(date_to_int(date1) - date_to_int(date2));
    }
190. 颠倒二进制位
模拟法 进行做题.
uint32_t reverseBits(uint32_t n) {
    uint32_t rev = 0;
    for (int i = 0; i < 32 && n > 0; ++i) {
        rev |= (n & 1) << (31 - i);  // 最多左移 31位.
        n >>= 1;
    }
    return rev;
}
好家伙, 位运算分治 ,然后一段一段移位..
    const uint32_t M1 = 0x55555555; // 01010101010101010101010101010101
    const uint32_t M2 = 0x33333333; // 00110011001100110011001100110011
    const uint32_t M4 = 0x0f0f0f0f; // 00001111000011110000111100001111
    const uint32_t M8 = 0x00ff00ff; // 00000000111111110000000011111111
public:
    uint32_t reverseBits(uint32_t n) {
        n = n >> 1 & M1 | (n & M1) << 1;
        n = n >> 2 & M2 | (n & M2) << 2;
        n = n >> 4 & M4 | (n & M4) << 4;
        n = n >> 8 & M8 | (n & M8) << 8;
        return n >> 16 | n << 16;
    }
1331. 数组序号转换
pair<int, int> 排序.
163. 缺失的区间
简单 分情况讨论 模拟题. 不过判断好复杂啊..
706. 设计哈希映射
我记得acwing讲过其他的做法.
这个是拉链法.
vector<list<pair<int,int>>> a; // 因为是um 直接存储pair了. 
static const int base = 10057; // 求哈希位置. 
static int hash(int key){return key%base;};
MyHashMap():a(base){ }
void put(int key, int value) {
    int h = hash(key);
    for(auto it = a[h].begin(); it != a[h].end();it++){
        if((*it).first==key){
            (*it).second = value;
            return;
        }
    }
    a[h].push_back({key,value});
}
int get(int key) {
    int h = hash(key);
    for(auto it = a[h].begin(); it != a[h].end(); it++){
        if((*it).first == key){
            return (*it).second;
        }
    }
    return -1;
}
void remove(int key) {
    int h = hash(key);
    for(auto it = a[h].begin(); it != a[h].end();it++){
        if((*it).first == key){
            a[h].erase(it) ;
            return;
        }         
    }
}
剑指 Offer 30. 包含min函数的栈
s 和 smin 两个栈就行.
119. 杨辉三角 II
简单的从又向左的dp题.
231. 2 的幂
32位int中 最大的2的幂 是 \(2^{30}\) 记下范围... \(2^{-31}<=n<2^{31}-1\)
二进制表示中:
- 移除最低位
n & (n - 1)- 原理: \((a10000)\) 和 \((a01111)\) & 以后的结果.
 
 - lowbit   
n & -n- 原理: n: \((a10000)\) -n:  \((\bar{a}01111)+(1) = (\bar{a}10000)\)
- & 以后可以取出来最低的那个.
 
 
 - 原理: n: \((a10000)\) -n:  \((\bar{a}01111)+(1) = (\bar{a}10000)\)
 

                
            
        
浙公网安备 33010602011771号