コードカプリス - 配列

理論的根拠

配列とは何ですか?

配列は、連続したメモリ空間に格納された同じタイプのデータのコレクションです。

二分探索

ここに画像の説明を挿入

解決策は 2 つあります: 左閉じ、右閉じ、左閉じ、右開き

左を閉じて右を閉じる

即[左、右]

class Solution {
    
    
public:
    int search(vector<int>& nums, int target) {
    
    
		int left = 0;
        int right = nums.size() - 1; //定义为左闭右闭
        while (left <= right) {
    
     //见注1
            //这一步等同于(left + right) / 2,如下处理为了防止内存溢出
            int middle = left + ((right - left) / 2);
            if (nums[middle] > target) {
    
     //说明target在左区间
                right = middle - 1;
            }else if (nums[middle] < target) {
    
    
                left = middle + 1;
            }else {
    
    
                return middle;
            }
        }
        return -1;
    }
};

ノート

  1. left-closed と right-closed が定義されているため、left が right になることができます。<=

左が閉じた状態 右が開いた状態

即[左、右)

class Solution {
    
    
public:
    int search(vector<int>& nums, int target) {
    
    
		int left = 0;
        int right = nums.size(); //定义为左闭右开
        while (left < right) {
    
     //left取不到right
            int middle = left + ((right - left) / 2);
            if (nums[middle] > target) {
    
    
                right = middle; //左区间是[left,middle)
            }else if (nums[middle] < target) {
    
    
                left = middle + 1;
            }else {
    
    
                return middle;
            }
        }
        return -1;
    }
};

要素を削除する

ここに画像の説明を挿入

2つの解決策:暴力的方法、ダブルポインタ方法

暴力の法則

2 つの for ループで要素を前方に上書きします

class Solution {
    
    
public:
    int removeElement(vector<int>& nums, int val) {
    
    
		int size = nums.size();
        for (int i = 0; i < size; i++)  {
    
     //第一个for循环遍历数组元素
            if (nums[i] == val) {
    
    
                for (int j = i + 1; j < size; j++) {
    
     //第二个for循环更新数组
                    nums[j - 1] = nums[j];
                }
                i--; //i后的元素都向前移了一位,所以i--
                size--;
            }
        }
        return size;
    }
};

時間計算量: O(n^2)

空間の複雑さ: O(1)

ダブルポインタ方式

2 つのポインタ (ファスト ポインタとスロー ポインタ) を使用して、2 層の for ループの動作を 1 層の for ループで実現します。

class Solution {
    
    
public:
    int removeElement(vector<int>& nums, int val) {
    
    
		int slowIndex = 0;
        for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) {
    
    
            //若找到该元素,fastIndex++,slowIndex不动
            if (nums[fastIndex] != val) {
    
    
			//在下一次循环,用fastIndex指向的元素覆盖slowIndex的
                nums[slowIndex] = nums[fastIndex];
                slowIndex++;
            }
        }
        return slowIndex;
    }
};

時間計算量: O(n)

空間の複雑さ: O(1)

最小の部分配列

ここに画像の説明を挿入

2 つの解決策: 暴力的な方法、スライディング ウィンドウ

暴力の法則

最初の for ループはすべての要素を反復し、2 番目の for ループはその要素から配列の末尾まで検索します。

class Solution {
    
    
public:
    int minSubArrayLen(int target, vector<int>& nums) {
    
    
		int result = INT32_MAX; //结果
        int sum = 0;
        int subLength = 0; //记录最小长度
        for (int i = 0; i < nums.size(); i++) {
    
    
            sum = 0;
            for (int j = i; j < nums.size(); j++) {
    
    
                sum += nums[j];
                if (sum >= target) {
    
     //一旦和大于target,记录最小长度
                    subLength = j - i + 1;
                    result = result < subLength ? result : subLength;
                    break;
                }
            }
        }
        return result == INT32_MAX ? 0 : result;
    }
};

時間計算量: O(n^2)

空間の複雑さ: O(1)

スライドウィンドウ

class Solution {
    
    
public:
    int minSubArrayLen(int target, vector<int>& nums) {
    
    
		int result = INT32_MAX;
        int sum = 0;
        int subLength = 0;
        int i = 0; //记录窗口起始位置
        for (int j = 0; j < nums.size(); j++) {
    
    
            sum += nums[j];
            while (sum >= target) {
    
    
                subLength = j - i + 1;
                result = result > subLength ? subLength : result;
                //滑动窗口的精髓,i一直在变
                sum -= nums[i++];
            }
        }
        return result == INT32_MAX ? 0 : result;
    }
};

時間計算量: O(n)

空間の複雑さ: O(1)

スパイラルマトリックス

ここに画像の説明を挿入

ループ不変条件で永続化: 左閉じ、右開き

class Solution {
    
    
public:
    vector<vector<int>> generateMatrix(int n) {
    
    
		vector<vector<int>> res(n, vector<int>(n, 0));
        int startx = 0, starty = 0;
        int loop = n / 2; //圈数,n=3时就一圈
        int mid = n / 2; //如果n为奇数,最后要给中间位置赋值
        int count = 1; //记录赋的值
        int offset = 1; //控制每圈的长度,但不是长度
        int i, j;
        while (loop--) {
    
    
            i = startx;
            j = starty;
            //四次循环就是一圈
            for (j = starty; j < starty + n - offset; j++) {
    
    
                res[startx][j] = count++;
            }
            for (i = startx; i < startx + n - offset; i++) {
    
    
                res[i][j] = count++;
            }
            for (; j > starty; j--) {
    
    
                res[i][j] = count++;
            }
            for (; i > startx; i--) {
    
    
                res[i][j] = count++;
            }
            
            //每次循环后的处理
            startx++;
            starty++;
            offset += 2;
        }
        //如果是奇数
        if (n % 2) {
    
    
            res[mid][mid] = count;
        }
        return res;
    }
};

おすすめ

転載: blog.csdn.net/qq_50209297/article/details/130635160