.

  • 树状数组
  • lc 307. 区域和检索 - 数组可修改
  • n数之和问题
  • 三数之和 四数字之和
  • 位运算
  • lc 371. 两整数之和
  • 构造
  • lc 667. 优美的排列 II
  • 字符串
  • 【字符串拼接】lc 273. 整数转换英文表示
  • dp
  • 【最长上升子序列】华为机试 HJ103 Redraiment的走法
  • 最长回文子串
  • HJ85 最长回文子串【字符串预处理】

树状数组

lc 307. 区域和检索 - 数组可修改

class NumArray {
public:
    
    vector<int> a;
    vector<int> c;
    int n=0;
    int low(int i){
        return i&(-i);
    }
    
    NumArray(vector<int>& nums) {
        a = std::move(nums);
        n = a.size();
        c = vector<int>(a.size()+1,0);
        for(int i=1;i<=n;++i){
            updatec(i,a[i-1]);
        }
    }
    
    void updatec(int i, int val) {
        
        for(;i<=n; i += low(i)){
           c[i]+= val;
        }
    }
    
    void update(int i, int val) {
        updatec(i+1,val-a[i]);
        a[i]=val;
    }
    
    int getsum(int r){
        int ret =0;
        for(;r>=1;r -= low(r)){
           ret+=c[r]; 
        }
        return ret;
    }
    
    int sumRange(int left, int right) {
        return getsum(right+1) - getsum(left);
    }
};

【code】类别归纳_c++

n数之和问题


位运算

lc 371. 两整数之和

class Solution {
public:
    int getSum(int a, int b) {
        
        int axorb = (a^b);
        int aandb = (unsigned int)(a&b)<<1;
        while(aandb){
            auto jin = (unsigned int)(aandb & axorb) << 1;
            axorb ^= aandb;
            aandb = jin;
        }
        return axorb;
        
    }
};

可以看做是一个递归的过程
LeetCode不允许超过int赋值,但是unsigned int 超过范围,直接做了截断
我在vs调试的时候 不用(unsigned int)也是可以的

a+b可以看做是两个部分的加法
1. a^b 无进位加法
2. (a&b)<<1 需要加上的进位
计算 a^b + ((a&b)<<1)

计算不进位的很容易,直接异或就行了

加上进位的时候,其实这个问题,就是原问题,
只不过a+b,只不过此时的b最后一位是0
可以看做是一种问题规模的缩小,因为当b全是0的时候,a就是答案了
所以递归的版本也比较容易理解了

需要注意的是统一符号,负数的加法,符号位应该怎么确定呢?

以3个二进制位举例(第一位是符号位)

-3

-2

-1

-0

0

1

2

3

原码

111

110

101

100

000

001

010

011

反码

100

101

110

111

000

001

010

011

补码

101

110

111

100

000

001

010

011

100

101

110

111

100

000

001

010

011

按照二进制加法,
使用原码 在-3+1!= -2

从反码中可以看到
-3+1 = -2,实现了负数范围内二进制加法和正数的统一
但是有两个0的,就会出现问题,-1+1=-0 然后-1+2 = +0
此时3+1 = -3

这显然不是我们想要的
所以将负数的反码进行一个修正,就是整体向右移动一位
这样一来-1修正之后的码就和(-0)的反码一样,-1+1 = +0
从而-1和+0就连续了,这个修正之后也就是补码
但是之前的-0似乎没用了,就可以用来表示-4,
此时3+1 = -4

查看二进制

template<class T> 
void printBinary(const T& x) {
    int n = (sizeof x) * 8;
    char* s = (char*)&x;
    cout << x << "\t: ";
    for (int i = n - 1; i >= 0; --i) {
        int a = i / 8, b = i % 8;
        if ((s[a]) & (1 << b))printf("1");
        else printf("0");
        if (b == 0)printf(" ");
    }
    cout << endl;
}

构造

lc 667. 优美的排列 II

使用前k+1个数字就可以构造出k个不同的数,后面的直接放进去就行
以n=10,k=4为例
从1开始 +4 -3 +2 -1 后面的直接填上去就行
1 5 2 4 3 6 7 8 9 10

class Solution {
public:
    vector<int> constructArray(int n, int k) {
        vector<int> ret = {1};
        int  c = 1;
        for (int i = k; i >= 1; --i) {
            if (ret.size() % 2 == 1) {
                c += i;
            }
            else {
                c -= i;
            }
            ret.push_back(c);
        }
        c = k + 1;
        while (ret.size()<n) {
            ++c;
            ret.push_back(c);
        }
        return ret;
    }
};

【code】类别归纳_c++_02

字符串

【字符串拼接】lc 273. 整数转换英文表示

class Solution {
public:

    unordered_map<int, string> m = {
        {1, "One"},
        {2, "Two"},
        {3, "Three"},
        {4, "Four"},
        {5, "Five"},
        {6, "Six"},
        {7, "Seven"},
        {8, "Eight"},
        {9, "Nine"},
        {10, "Ten"},
        {11, "Eleven"},
        {12, "Twelve"},
        {13, "Thirteen"},
        {14, "Fourteen"},
        {15, "Fifteen"},
        {16, "Sixteen"},
        {17, "Seventeen"},
        {18, "Eighteen"},
        {19, "Nineteen"},
        {20, "Twenty"},
        {30, "Thirty"},
        {40, "Forty"},
        {50, "Fifty"},
        {60, "Sixty"},
        {70, "Seventy"},
        {80, "Eighty"},
        {90, "Ninety"},
    };

    int Billion  = 1000000000;
    int Million  = 1000000;
    int Thousand = 1000;
    int Hundred  = 100;

    string int_str(int a) {
        stringstream ss;
        ss << a;
        return ss.str();
    }

    string help(int n) {

        string ret = "";
        if(n==0) return "Zero ";

        if (n >= Billion) {
            ret += help(n / Billion) + "Billion ";
            n -= n / Billion * Billion;
        }
        
        if (n >= Million) {
            ret += help(n / Million) + "Million ";;
            n -= n / Million * Million;
        }
        
        if (n >= Thousand) {
            ret += help(n / Thousand) + "Thousand ";
            n -= n / Thousand * Thousand;
        }
        
        if (n >= Hundred) {
            ret += help(n / Hundred) + "Hundred ";
            n -= n / Hundred * Hundred;
        }

        if (n >= 20) {
            ret += m[n / 10 * 10] + " ";
            n -= n / 10 * 10;
        }

        if (n >= 1) {
            ret += m[n] + " ";
        }
        
        return ret;
    }
    string numberToWords(int n) {
        auto s = help(n);
        return s.substr(0, s.size() - 1);
    }
};

【code】类别归纳_数据结构与算法_03

dp

【最长上升子序列】华为机试 HJ103 Redraiment的走法

URL:https://www.nowcoder.com/practice/24e6243b9f0446b081b1d6d32f2aa3aa?tpId=37&rp=1&ru=%2Fta%2Fhuawei&qru=%2Fta%2Fhuawei%2Fquestion-ranking

#include <iostream>
#include <vector>

using namespace std;
int n;
void f(){
     auto a = vector<int>(n,0);
    for(int i=0;i<n;++i){
        cin>>a[i];
    }
    auto dp =  vector<int>(n,1);
    int ret = 1;
    for(int i=1;i<n;++i){
        for(int j=0;j<i;++j){
            if( a[i]>a[j] ){
                dp[i] = max(dp[i],dp[j]+1);
                ret = max(ret,dp[i]);
            }
        }    
    }
    cout<<ret<<endl;
}
int main(){
    
    while(cin>>n)
    f();
    return 0;
}

最长回文子串

HJ85 最长回文子串【字符串预处理】

#include <iostream>

using namespace std;

#define debug(x) cout<<#x<<": "<<(x)<<endl;
int main(){
    string s;
    cin>>s;
    string sc = "#";
    for(auto c:s){
        sc += c;
        sc += "#";
    }
    //debug(sc);
    int n = sc.size();
    int ret=0;
    for(int i=0;i<n;++i){
        int j=0;
        while(i+j<n && i-j>=0){
            if(sc[i-j] != sc[i+j]){
                break;
            }  
            ++j;
        }
        ret = max(ret,j);
    }
    cout<<ret-1<<endl;
    return 0;
}