Leetcodeの問題解決アイデア分析(34)268-283

  1. 欠落している数字
    0、1、2、…、nにn個の数字が含まれるシーケンスが与えられた場合、シーケンスに表示されない0…nの数字を見つけます。

XOR 1つずつ、欠けている数は表示されない数です

class Solution {
    
    
public:
    int missingNumber(vector<int>& nums) {
    
    
    int res = nums.size();
    for(int i = 0; i < nums.size(); ++i)
        res = res ^ i ^ nums[i];            // a^b^b = a;
    return res ;
    }
};

  1. 整数変換英語表現
    非負整数を対応する英語表現に変換します

この質問は実際には難しくありません、それはすべての可能性をリストしてそれらを組み合わせ、スペースを追加することです

class Solution {
    
    
public:
    vector<string>num1 = {
    
    "","One","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten",
                        "Eleven","Twelve","Thirteen","Fourteen","Fifteen","Sixteen","Seventeen","Eighteen","Nineteen","Twenty"};
    vector<string>num2 = {
    
    "","","Twenty","Thirty","Forty","Fifty","Sixty","Seventy","Eighty","Ninety"};
    vector<string>num3 = {
    
    "Hundred","Thousand","Million","Billion"};//前面增加空字符串,方便单词数字与下标对应
    
    string numberToWords(int num) {
    
    
        if(num == 0)return "Zero";//单独考虑0
        string res = helper(num); 
        res.erase(0,1);
        return res; 
    }

    string helper(int num){
    
    
        if(num == 0){
    
    
            return "";
        }
        if(num<20){
    
    
            return " " + num1[num];
        }
        if(num<100){
    
    
            return " "+num2[num/10] + helper(num%10);
        }
        if(num < 1000){
    
    
            return helper(num/100)+" "+num3[0]+helper(num%100);
        }
        for(int i = 1; i <= 3; i++){
    
    
            if(num < pow(1000,i+1)){
    
    
                return helper(num/(int)pow(1000,i))+ " " + num3[i] + helper(num%(int)pow(1000,i));
            }
        }
        return "";
    }
};


  1. Hインデックス
    は、研究者の論文が引用された回数の配列です(研究者が引用された回数は非負の整数です)。研究者のhインデックスを計算するメソッドを記述します。
    hインデックスの定義:hは「高引用数」を表します。研究者のhインデックスは、N回の論文のうち彼(彼女)を指し、合計h回以上引用されたh件の論文を指します。(残りのN-hの論文はh回以下引用されます。)

質問の意味によれば、被引用数がNより多くても意味がなく、最大はNです。そのため、ここではカウントすることでソートし、さまざまなバケットにパックできます。必要なのは、h以上のhです。つまり、次のいくつかのバケットの総数は、バケットの数以上です。

class Solution {
    
    
public:
    int hIndex(vector<int>& citations) {
    
    
        int n = citations.size();
        vector<int> bucket(n + 1, 0);
        for (int i = 0; i < n ; i++)
        {
    
    
            if (citations[i] >= n)
                bucket[n]++;
            else 
                bucket[citations[i]]++;
        }
        int ret = 0;
        for (int i = n; i >= 0; i--)
        {
    
    
            if (ret < i)
            {
    
    
                if (ret + bucket[i] < i)
                    ret += bucket[i];
                else 
                    ret = i;
            }
            else 
                break;
        }
        return ret;
    }
};
  1. 最初の間違ったバージョン
    bool isBadVersion(version)インターフェイスを呼び出して、ユニットテストでバージョン番号のバージョンが間違っているかどうかを判断します。最初の間違ったバージョンを見つける関数を実装します。API呼び出しの数を最小限に抑える必要があります。

典型的な二分探索、唯一の罠は、midが数値制限を超える可能性があることに注意することです

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

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



  1. 完全な平方数
    正の整数nを指定して、合計がnになるように、いくつかの完全な平方数(1、4、9、16など)を見つけます。合計を構成する完全な正方形の数を最小限に抑える必要があります。

この問題は、動的プログラミングを使用して簡単に解決できます。数値Nの最小二乗数は、数値+ 1を構成するN`の二乗数です。つまり、各Nについて、1からN-1までの最小の解を持つ人を観察し、次にNの解これは+1です。ただし、N = IxI + N 'を満たさない組み合わせがあるため、1からN + 1までのすべての数値を観察する必要はありません。たとえば、2 =でないため、12 = 2 + N'は必要ありません。ある数の二乗。したがって、観察の範囲を大幅に縮小する必要があります。

class Solution {
    
    
public:
    int numSquares(int n)
    {
    
    
        vector<int> result(n+1, 0x7FFFFFFF); // 每个数的最优解都存在result数组里
        result[0] = 0;
        for (int i = 1; i <= n; i++){
    
    
            for(int j = 1; i - j * j >= 0 ; j++) {
    
      // 观察比N小的数,且符合N = IxI + N'的数值
                result[i] = min(result[i], result[i - j * j] + 1); // 把最优解(最小值)+ 1 写入result
            }
        }
        return result[n];
    }
};
  1. 式に演算子を追加し
    ます。0〜9の数値とターゲット値のみを含む文字列を指定し、数値の間に二項演算子(単項ではない)+、-、または*を追加して、ターゲット値を取得できるすべての式を返します式。

バックトラッキング方式で解決可能ですが、足し算や引き算よりも乗算の方が優先されるなど、細かいところまで考えるのが面倒です。4つの操作があります。1.プラス記号を追加します。2.マイナス記号を追加します。3.乗算記号を追加します。4.次の数値を追加して、より大きなオペランドを形成します。文字列を取得している間に式の値をすぐに計算するために、アルゴリズム中にいくつかの中間値を維持する必要があります。

typedef long long LL;
class Solution {
public:
    vector<string> res;
    string path;
    vector<string> addOperators(string num, int target) {
        if(num == ""){
            return {};
        }
        dfs(0,0,1,num[0] - '0',1,num.size(),target,num);
        return res;
    }

    void dfs(int idx,LL pre,LL left,LL operand,int sign,int n,int target,string& num){
        //查看串尾是否运算符来判断当前数字是否操作数的首位
        bool isBeg = path.empty() || path.back() < '0'; 

        path += num[idx];
        if(idx == n - 1){
            if(pre + sign * left * operand == target){
                res.emplace_back(path);
            }
        }else{
            int next_num = num[idx + 1] - '0';
            string old_path = path;
            //追加数字时不能形成有前导0的情况
            if(!(isBeg && num[idx] == '0')){  
                dfs(idx + 1,pre,left,operand * 10 + next_num,sign,n,target,num);
                path = old_path;
            }
            path += '+';
            dfs(idx + 1,pre + sign * left * operand,1,next_num,1,n,target,num);
            path = old_path;

            path += '-';
            dfs(idx + 1,pre + sign * left * operand,1,next_num,-1,n,target,num);  
            path = old_path;

            path += '*';
            dfs(idx + 1,pre,left * operand,next_num,sign,n,target,num);
        }
    }
};


  1. ゼロの移動
    配列numsを指定して、ゼロ以外の要素の相対的な順序を維持しながら、すべてのゼロを配列の末尾に移動する関数を記述します。

最も簡単な方法は、最初から最後までトラバースし、0を削除して最後に追加することです。これは、stlを使用して簡単に解決できます。ゼロ以外の要素が見つかった場合は、現在のポインターとスローポインターが指している要素を交換してから、2つのポインターを進める必要があります。ゼロ要素の場合、現在のポインタのみを進めます。

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int cnt = 0;
        vector<int>::iterator iter = nums.begin();
        while (iter != nums.end())
        {
            if (*iter == 0)
            {
                cnt++;
                iter = nums.erase(iter);
            }
            else iter++;
        }
        for (int i = 0; i < cnt; i++)
            nums.push_back(0);

        return;
    }
};
class Solution {
public:
    void moveZeroes(vector<int>& nums) 
    {
        for (int i = 0, cur = 0; cur < nums.size(); cur++) 
        {
            if (nums[cur] != 0) 
            {
                swap(nums[i++], nums[cur]);
            }
        }
    }
};

おすすめ

転載: blog.csdn.net/u013354486/article/details/107548849