加载中...

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

我自己模拟很容易出现模拟不清晰的情况.

还有尽量用 islowerisupper.

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)\)
      • & 以后可以取出来最低的那个.








posted @ 2022-01-26 17:13  benenzhu  阅读(35)  评论(0)    收藏  举报