Leetcode array 數組題目解題報告

1. Remove Duplicates from Sorted Array

Description: Easy

Given a sorted array nums, remove the duplicates in-place such that each element appear only once and return the new length.

Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.

Given nums = [1,1,2],
Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively.
It doesn't matter what you leave beyond the returned length.

Analysis

a. 數組前提是有序的,從一個數組中去掉重復元素后,返回這個數組的長度。

b. 不能利用其它多余空間。

Solution 1:雙游標法

code and annotation

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        // 首先考慮兩種最簡單的情況,數組大小為0和1,這兩種情況都可以直接返回結果
        // 這兩種情況返回值正好是數組大小,下面這行代碼正好表達了這個過程
        if(nums.size()<=1)
            return nums.size();
        else
        {
            // index_new指針記錄當前發現的不重復的元素的‘數量’
            // 并且這個索引指向的值是最新的不重復元素的值
            int index_new = 0
            // each指針開始從第二個元素遍歷數組剩余元素
            for(int each = 1; each<nums.size(); each++)
            {
              // 遍歷過程中發現新的元素,開始更新
              if(nums[index_new] != nums[each])
              {
                // 更新已發現的不重復元素數量
                index_new++;
                // 更新最新的不重復元素值
                nums[index_new] = nums[each];
              }
            }
            // 注意index_new是從0開始的,當有兩個不重復元素,index_new為1,所以最后結果還要加1
            return index_new + 1;
        }
    }
};

tips

  • 實際是雙游標法,一個負責遍歷,一個負責記錄。
  • 利用兩個指針,一個指針記錄當前發現的不重復的元素的‘數量’,并且這個索引指向的值是最新的不重復元素的值。初始位置為0。
  • 另一個指針遍歷數組的每一個元素。初始位置為1。
  • 遍歷數組時記得 <nums.size(), 沒有等號。數組大小是數組最大索引加1。
  • 遍歷指針更新就是不斷加1,數量指針的更新是關鍵(發現新元素)。

Solution 2:利用STL

code and annotation

class Solution {
public:
    int removeDuplicates(vector<int>& nums){
        // 利用unique函數, 返回一個迭代器指針(去重后的尾地址)
        auto iLocator = unique(nums.begin(), nums.end());
        // distance函數計算元素偏移量
        return distance(nums.begin(), iLocator);
    }
};

tips

  • unique接收兩個迭代器,作用是“去掉”容器中相鄰元素的重復元素(不一定要求數組有序),它會把重復的元素添加到容器末尾(所以數組大小并沒有改變),而返回值是去重之后的尾地址。(這個尾地址是最后一個未重復的后一個位置)
  • distance也是接收兩個迭代器,計算兩者的偏移量。


2. Remove Duplicates from Sorted Array Ⅱ

Description: Medium

Given a sorted array nums, remove the duplicates in-place such that duplicates appeared at most twice and return the new length.

Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.

Given nums = [1,1,1,2,2,3],
Your function should return length = 5

Analysis

a. 這道題跟Remove Duplicates from Sorted Array比較類似,區別只是這里元素可以重復出現至多兩次,而不是一次。其實也比較簡單,只需要維護一個counter,當counter是2時,就直接跳過即可,否則說明元素出現次數沒有超,繼續放入計數的指針,若遇到新元素則重置counter。

b. 但其實這里的前提是數組已經有序,其實如果遍歷指針i掃到的當前元素在index之前已經存在兩個(注意,由于A是排好序的,因此只需要判斷前兩個就行),那么i繼續前進。否則將i指向的元素加入index,index與i一起前進。

Solution 1

code and annotation

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        int n = nums.size();
        // 注意最簡單的情況是數組大小0,1,2
        if(n<=2)
            return n;
        else
        {
            // 記錄指針和遍歷指針初始都是2
            int index_new = 2;
            for(int i = 2; i<n; i++){
                if(nums[i] ! = nums[index_new])
                {
                    nums[index_new] = nums[i];
                    index_new++;
                }
            }
            return index_new;
        }
    }
};

tips

  • 不同之處是兩種指針的初始值設置;
  • 記錄指針的更新策略其實也是一樣的。


3. Search in Rotated Sorted Array

Description: Medium

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]).

You are given a target value to search. If found in the array return its index, otherwise return -1.

You may assume no duplicate exists in the array.

Your algorithm's runtime complexity must be in the order of O(log n).

analysis

a. 一個有序(升)的數組進行旋轉。并且這個旋轉的中心點也不確定,再在這個數組里尋找某個元素的位置。
b. 沒有重復元素
c. 任取一個位置,其左右兩邊必有一邊是有序的。那么在這個有序表里查找某個元素就可以使用二分法。

Solution

code and annotation

class Solution {
public:
    int search(vector<int>& nums, int target) {
        // 線性表搜索問題一般都會用到二分法
        // 二分法涉及三個指針min max mid
        int min = 0, max = nums.size()-1, mid = 0;
        // 二分法最終的停止條件
        while(min <= max){
            // 初始第一次二分的mid
             int mid = (min+max)/2;
             // 如果mid恰好是target(最終target都會到mid這里)
             if(nums[mid] == target)    return mid;
             // 如果左半部分有序,則在此半部分(有序字符串)進行二分查找
             if(nums[min] <= nums[mid]){
                 if(nums[min]<=target && target<nums[mid])
                    max = mid - 1;
                else
                    min = mid + 1;
             }
             // 如果右半部分有序
             else{
                 if(nums[mid]< target && target<=nums[max])
                    min = mid + 1;
                else
                    max = mid - 1;
             }
        }
        // 不滿足最高二分條件min<=max時
        return -1;
    }
};

tips

  • 在旋轉數組里搜索元素,看起來有點麻煩,其實理清了比較簡單。仍然采用切一半二分。但是由于是有序旋轉的,所以切一半會有問題。所以需要進一步判斷。

  • 假設數組是A,每次左邊緣為l,右邊緣為r,還有中間位置是m。在每次迭代中,分三種情況:

    (1)如果target==A[m],那么m就是我們要的結果,直接返回;

    (2)如果A[m]<A[r],那么說明從m到r一定是有序的(沒有受到rotate的影響),那么我們只需要判斷target是不是在m到r之間,如果是則把左邊緣移到m+1,否則就target在另一半,即把右邊緣移到m-1。

    (3)如果A[m]>=A[r],那么說明從l到m一定是有序的,同樣只需要判斷target是否在這個范圍內,相應的移動邊緣即可。

二分法大體框架

vector<int> N; int target
int left = 0;
int right = size-1;
int mid = 0;
while(left <= right)
{
    mid = (left + right)/2;
    if(N[mid] == target)
        return mid;
    if(N[left] <= target && target < N[mid])
        right = mid - 1;
    else
        left = mid + 1;
}

// 二分法前提是用在有序數組,并且要注意二分法的停止條件以及大體框架
// 二分法最終return的都是mid
// 注意幾次等號邊界,target和mid的第一處if等號,其余都不等


4. Search in Rotated Sorted Array II

Description: Medium

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., [0,0,1,2,2,5,6] might become [2,5,6,0,0,1,2]).

You are given a target value to search. If found in the array return true, otherwise return false.

Input: nums = [2,5,6,0,0,1,2], target = 0

Output: true

Input: nums = [2,5,6,0,0,1,2], target = 0

Output: true

Analysis

a. 和之前一條題目相比僅僅是多了重復元素的限制
b. 之前沒有重復元素,判斷左邊還是右邊有序,只需考慮nums[left]<=nums[mid],這里取等號,是因為我們知道沒有重復元素。
c. 有了重復元素,只需把上面一個判斷分成兩步即可,當nums[left]=num[mid]時,跳過該重復元素。

Solution

code and annotation

class Solution {
public:
    bool search(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size()-1;
        int mid = 0;
        while(left <= right)
        {
            mid = (left + right)/2;
            if(nums[mid] == target)
                return true;
            if(nums[left] < nums[mid])
            {
                if(nums[left]<=target && target<nums[mid])
                    right = mid - 1;
                else
                    left = mid + 1;
            }
            **else** if(nums[left] == nums[mid])
                left++;
            else
            {
                if(nums[mid] < target && target <= nums[right])
                    left = mid + 1;
                else
                    right = mid - 1;
            }
        }
        return false;
        
    }
};

tips

  • 有序表查找需要熟記二分法
  • code中打*號的else,去掉代碼即失效。


5. Median of Two Sorted Arrays

Description: Hard

There are two sorted arrays nums1 and nums2 of size m and n respectively.

Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

Example 1:
nums1 = [1, 3]
nums2 = [2]
The median is 2.0

Example 2:
nums1 = [1, 2]
nums2 = [3, 4]
The median is (2 + 3)/2 = 2.5

Analysis

a. 兩個有序的數組,找到合并后的數組中中間的值。
b. 這個題目可以轉換為一個更普適的版本,給定兩個已經排好序的數組,找到兩者所有元素中第k大的元素。

c. O(m+n)的解法比較直觀,直接合并兩個數組后排序,再找到第k大的元素。但是不符合本題的復雜度要求。

d. 另一種思路,其實,我們求第k大的元素,是不需要“排序”這么復雜的操作的。我們可以設立一個計數器count記錄當前找到的第k大的元素,同時設立兩個指針,PA, PB,分別指向A,和B兩個數組的第一個元素。如果此時*PA較小,則PA++, count++。等count==k時,我們就找到了那個元素。O(k)的時間,O(1)的空間。但是k接近m+n時,還是O(m+n)。

e. 還有什么好的思路嗎?我們刪除在k之前的元素必須一個個找嗎?假如我們刪除一半一半呢,我們要充分利用有序這一個特點。類似于二分法。

Solution

code and annotation

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int m = nums1.size();
        int n = nums2.size();
        int total = m + n;
        // 判斷總數奇偶,奇數直接去中間數,偶數求兩個值取平均
        // total是數量,注意中間值的索引。
        if(total & 0x1)
            return find_kth(nums1.begin(), m, nums2.begin(), n, total/2);
        else
            return (find_kth(nums1.begin(), m, nums2.begin(), n, total/2)
            + find_kth(nums1.begin(), m, nums2.begin(), n, total/2 - 1))/2.0;
private:
    // 定義找到第k個數的遞歸函數,A,B是兩個迭代器
    static int find_kth(auto A, int m, auto B, int n, int k)
        {
            // 保證輸入的第一個數組要比第二個大,這樣可以簡化后面的代碼
            if(m < n)
                return find_kth(B, n, A, m, k);
            // 遞歸停止條件
            // 至少有一個數組大小為0,因為m較小,只討論m
            if(m == 0)
                return *(B + k - 1);
            if(k == 1)
                return min(*A, *B);
            // 保證ia+ib = k
            // 注意此時 ia ib仍然是數量,注意算索引要減一;
            int ia = min(m, k/2);
            int ib = k - ia;
            // 開始對ia ib進行三種判斷,分別對應三種情況
            if(*(A + ia -1) < *(B + ib - 1))
                return find_kth(A+ia-1+1, m-ia, B, n, k-ia);
            else if(*(A + ia -1) > *(B + ib - 1))
                return find_kth(A, m, B+ib-1+1, n-ib, k-ib);
            else
                // 想一想,恰恰是相等的情況讓我們能夠理解為什么這么做。
                return *(A + ia - 1);
        }
    }
};

tips

  • 核心思想:每個數組取k/2(較小數組小于k/2時,取m,保證兩者取的加起來為k),當A[k/2 - 1]==B[k/2 - 1]時,第k大的值恰好是該相等值。這就促使我們分析另兩種情況,A[k/2 - 1]<B[k/2 - 1]時,A[0]到A[k/2 -1]一定不是k大元素且比k小,那么我們就可以刪掉A數組的這些元素,變成A'。之后繼續在A’和B上找第k-k/2大的元素。
  • 遞歸函數一定要注意遞歸停止條件,return的是確定的值,而不是遞歸函數本身就是停止條件。
  • auto A --> std::vector<int>::const_iterator A


6. Longest Consecutive Sequence

Description: Hard

Given an unsorted array of integers, find the length of the longest consecutive elements sequence.

Your algorithm should run in O(n) complexity.

Example:

Input: [100, 4, 200, 1, 3, 2]
Output: 4
Explanation: The longest consecutive elements sequence is [1, 2, 3, 4]. Therefore its length is 4.

Analysis

a. 找到數組中連續的最長子數組的長度。
b. O(nlogn)的話可以先排序,但是這里不行。
c. 需要注意的是不能重復考慮。比如上面例子,1,2,3,4是最長連續數組,考慮過4后,就不能再去單獨考慮1,3,2。
d. 我們可以建立一個哈希映射,記錄每一個數是否被考慮過。再對每一個元素進行左右擴張,查找最大長度。

Solution

code and annotation

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        unordered_map<int, bool> used;
        // 哈希表每個key為nums元素,value初始為false,初始每個元素沒有考慮過。
        for(auto i : nums)
            used[i] = false;
        // 遍歷每一個元素
        int longest = 0;
        for(int i=0; i<nums.size(); i++)
        {
            // 如果發現這個元素被考慮過了,跳過該元素。
            if(used[nums[i]])
                continue;
            // 否則先把該元素設為考慮過了
            int length = 1;
            used[nums[i]] = true;
            // 以該元素在連續表上向右擴張
            for(int j = nums[i] + 1; used.find(j)!=used.end(); j++)
            {
                // 更新長度
                length += 1;
                // 并且把延伸的元素設為已考慮
                used[j] = true;
            }
            // 以該元素在連續表上向右擴張
            for(int j = nums[i] - 1; used.find(j)!=used.end(); j--)
            {
                // 更新長度
                length += 1;
                // 并且把延伸的元素設為已考慮
                used[j] = true;
            }
            // 考慮過一個未考慮的元素,更新最大長度
            longest = max(longest, length);
        }
        return longest;
    }
};

tips

  • 將vector映射到map是一種經常使用的策略。map的find函數可以幫助
  • 時間復雜度要求我們不能先對數組排好序。
  • find函數如果找不到元素,返回end
  • 使用哈希表監控每一個元素是否被使用過,可以大幅度減少算法復雜度。


7. Two Sum

Description: Easy

Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

Analysis

a. 給一個值,找出數組里相加和為該值的索引。

b. 遍歷每一個元素,計算gap,再找gap。 思想很簡單,但是找元素,以及建立索引和值的對應。顯然用哈希表

Solution

code and annotation

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        // 建立值-索引的map
        unordered_map<int, int> value_index;
        // 建立最終返回結果的vector
        vector<int> result;
        // vector到map 值-索引
        for(int i = 0; i<nums.size(); i++)
            value_index[nums[i]] = i;
        for(int i = 0; i<nums.size(); i++)
        {
            int gap = target - nums[i];
            // map是值-索引還是索引-值,取決于map的find函數是找key。
            if(value_index.find(gap)!=value_index.end() && 
            value_index[gap] != i){
                result.push_back(i);
                result.push_back(value_index[gap]);
                // 只需找到一對
                break;
            }
        }
        return result;
    }
};

tips

  • vector到map的映射,6,7題都有很好的表現
  • map find的是key,由此設計map


8. Remove Element

Description: Easy

Given an array nums and a value val, remove all instances of that value in-place and return the new length.

Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.

The order of elements can be changed. It doesn't matter what you leave beyond the new length.

Example 1:

Given nums = [3,2,2,3], val = 3,

Your function should return length = 2, with the first two elements of nums being 2.

Analysis

a. 刪除掉一個數組內所有指定的元素,然后返回數組長度

b. 其實本題看起來有很簡單的思路,用一個數組,遍歷給定的數組,如果遍歷的元素不是target就加入建立的新數組。但是這樣空間復雜度很高。

c. 存在一個空間復雜度為1的方法,就是利用雙游標,只在原數組上進行覆蓋。(類似鏈表刪除的操作)

Solution 1: 雙游標

code and annotation

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        // 相當于新數組的游標
        int index = 0;
        // 遍歷
        for(int i = 0; i<nums.size(); i++)
        {
            if(nums[i] != val)
            {
                nums[index] = nums[i];
                index++;
            }
        }
        return index;
    }
};

Solution 2: STL

code and annotation

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        return distance(nums.begin(), remove(nums.begin(), nums.end(), val));
    }
};

tips

  • distance接收兩個迭代器,計算兩者偏移量
  • remove()函數接收兩個迭代器和一個元素,返回去掉這個元素后的最后一個迭代器。
  • 熟悉STL函數可以方便解題。


9. Rotate image

Description: Medium

You are given an n x n 2D matrix representing an image.

Rotate the image by 90 degrees (clockwise).

You have to rotate the image in-place, which means you have to modify the input 2D matrix directly. DO NOT allocate another 2D matrix and do the rotation.

Given input matrix =
[
[1,2,3],
[4,5,6],
[7,8,9]
],

rotate the input matrix in-place such that it becomes:
[
[7,4,1],
[8,5,2],
[9,6,3]
]

Analysis

a. 將一個n*n的矩陣旋轉90度,并且不能使用另外的空間,只能在原始矩陣上進行操作

b. 最簡單的思路是從外到內一圈圈旋轉,但這種方法比較慢。

c. 從觀察角度會發現,旋轉90度可以拆分為首先沿著水平中線翻轉一次,然后再沿著主對角線翻轉一次。而這兩個操作實現比較容易

Solution

code and annotation

class Solution {
public:
    void rotate(vector<vector<int>>& matrix) {
        const int n = matrix.size();
        # 先水平翻轉
        for(int i = 0; i<n/2; ++i)
            for(int j = 0; j<n; ++j)
                swap(matrix[i][j], matrix[n-1-i][j]);
        
        # 再沿著主對角線翻轉
        for(int i = 0; i<n; ++i)
            for(int j =i+1; j<n; ++j)
                swap(matrix[i][j], matrix[j][i]);
    }
};

tips

  1. 分解思想:旋轉90度可以分解為兩個簡單操作

  2. 索引的邊界可以畫圖一步步獲得。



10. Plus One

Description: Medium

Given a non-empty array of digits representing a non-negative integer, plus one to the integer.

The digits are stored such that the most significant digit is at the head of the list, and each element in the array contain a single digit.

You may assume the integer does not contain any leading zero, except the number 0 itself.

Analysis

a. 實際上就是一次加法的模擬,這里的加數是1,其實可以拓展為通用的加數(0到9)

b. 從最后一位數字開始一直加到最后一位----更新當前被加數字----更新進位: 與10的除數----再次更新當前被加值:與10的余數。

Solution

code and annotation

class Solution {
public:
    vector<int> plusOne(vector<int>& digits) {
        add(digits, 1);
        return digits;  
    }
private:
    // 0<=plusnumber<10
    void add(vector<int>& digits, int plusnumber){
        // 最后加的數字可以看成第一次的進位
        int c = plusnumber;
        // 從最后一位數字開始一直加到最后一位
        for(auto it = digits.rbegin(); it!=digits.rend(); ++it)
        {
            // 更新當前被加數字
            *it += c;
            // 更新進位: 與10的除數
            c = *it/10;
            // 再次更新當前被加值:與10的余數
            *it %= 10;
        }
        // 如果計算完所有數值,進位還不是0,說明位數需要增加
        if(c!=0)
            digits.insert(digits.begin(), 1);
    }
};

tips

c.begin() 返回一個迭代器,它指向容器c的第一個元素

c.end() 返回一個迭代器,它指向容器c的最后一個元素的下一個位置

c.rbegin() 返回一個逆序迭代器,它指向容器c的最后一個元素

c.rend() 返回一個逆序迭代器,它指向容器c的第一個元素前面的位置



11. Climbing Stairs

Description: Medium

You are climbing a stair case. It takes n steps to reach to the top.

Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?

Note: Given n will be a positive integer.

Analysis

a. 很有趣的一條題目,如果有n個階梯,你每次可以走一級或兩級,問一共有多少種走法?

b.

1.假設當有n個臺階時假設有f(n)種走法。

2.青蛙最后一步要么跨1個臺階要么跨2個臺階。

3.當最后一步跨1個臺階時即之前有n-1個臺階,根據1的假設即n-1個臺階有f(n-1)種走法。

4.當最后一步跨2個臺階時即之前有n-2個臺階,根據1的假設即n-2個臺階有f(n-2 )種走法。

5.顯然n個臺階的走法等于前兩種情況的走法之和即f(n)=f(n-1)+f(n-2)。

c. 本質上是一個 斐波那契數列

Solution

code and annotation

class Solution {
public:
    int climbStairs(int n) {
        if(n<=2)
            return n;
        else
        {
            int first = 1, second = 2, third = 0;
            for(int i = 3; i<=n; ++i)
            {
                third = first + second;
                first = second;
                second = third;
            }
            return third;
        }
        
    }
};


12 Set Matrix Zeroes

Decription:easy

Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in-place.

Analysis

  1. 一個m*n的矩陣,如果有一個元素為0,則將其一行和一列的數字都變為0;
  2. 這是一個很有趣的題目,對復雜度考察很到位。
  3. 最大的問題就是我們遇到0的時候不能直接把矩陣的行列在當前矩陣直接置0,否則后面還沒訪問到的會被當成原來是0,最后會把很多不該置0的行列都置0了。
  4. 一個直接的想法是備份一個矩陣,然后在備份矩陣上判斷,在原矩陣上置0,這樣當然是可以的,不過空間復雜度是O(m*n),判斷和置零分開坐。
    5.判斷某一項是不是0只要看它對應的行或者列應不應該置0就可以,所以我們可以維護一個行和列的布爾數組,然后掃描一遍矩陣記錄那一行或者列是不是應該置0即可,這種方法的空間復雜度是O(m+n)。
  5. 還有什么方法可以進一步降低復雜度呢,我們考慮使用第一行和第一列來記錄上面所說的行和列的置0情況,這里問題是那么第一行和第一列自己怎么辦?想要記錄它們自己是否要置0,只需要兩個變量(一個是第一行,一個是第一列)就可以了。然后就是第一行和第一列,如果要置0,就把它的值賦成0(反正它最終也該是0,無論第一行或者第一列有沒有0),否則保留原值。然后根據第一行和第一列的記錄對其他元素進行置0。最后再根據前面的兩個標記來確定是不是要把第一行和第一列置0就可以了。這樣的做法只需要兩個額外變量,所以空間復雜度是O(1)。

Solution1 O(m+n)

class Solution {
public:
void setZeroes(vector<vector<int> > &matrix) {
  const size_t m = matrix.size();
  const size_t n = matrix[0].size();
  vector<bool> row(m, false); // 標記該行是否存在0
  vector<bool> col(n, false); // 標記該列是否存在0
  for (size_t i = 0; i < m; ++i) {
    for (size_t j = 0; j < n; ++j) {
      if (matrix[i][j] == 0) {
        row[i] = col[j] = true;
        }
      }
    }
  for (size_t i = 0; i < m; ++i) {
    if (row[i])
      fill(&matrix[i][0], &matrix[i][0] + n, 0);
    }
  for (size_t j = 0; j < n; ++j) {
    if (col[j]) {
      for (size_t i = 0; i < m; ++i) {
        matrix[i][j] = 0;
      }
    }
  }
  }
};

Solution2 O(1)

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        
        int m=matrix.size();
        int n=matrix[0].size();
        bool row0=false;//標記第一行是否存在0
        bool column0=false;//標記第一列是否存在0
        
        if(m==0||n==0)return;//特殊情況處理
        for(int i=0;i<m;i++)
        {
            if(matrix[i][0]==0)column0=true;//第一列存在0
        }
        
        for(int i=0;i<n;i++)
        {
            if(matrix[0][i]==0)row0=true;//第一行存在0
        }
        
        for(int i=1;i<m;i++)//遍歷除第一行和第一列以外的行列
        {
            for(int j=1;j<n;j++)
            {
                if(matrix[i][j]==0)
                {
                    matrix[0][j]=0;//存儲0元素出現的列下標
                    matrix[i][0]=0;//存儲0元素出現的行下標
                }
            }
        }
        
        for(int i=1;i<m;i++)
        {
            for(int j=1;j<n;j++)
            {
                if(matrix[0][j]==0||matrix[i][0]==0)//對應行列全部置零
                matrix[i][j]=0;
            }
        }
        if(row0==true)//如果第一行存在零,第一行置零
        {
            for(int i=0;i<n;i++)
            matrix[0][i]=0;
        }
        if(column0==true)//如果第一列原始存在0,則第一列置零
        {
            for(int i=0;i<m;i++)
            matrix[i][0]=0;
        }
        
    }
};
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • rljs by sennchi Timeline of History Part One The Cognitiv...
    sennchi閱讀 7,448評論 0 10
  • 1. Two Sum 用hash可以得到O(n)時間的解法,用python中的enumerate函數,可以獲得元素...
    Morphiaaa閱讀 450評論 0 0
  • 我之前暗戀一個男生,兩年,很普通很普通的一個人,可我就是喜歡他。他喜歡過一段時間我閨蜜,可是我閨蜜到最后也沒有答應...
    你嘗一口我閱讀 457評論 0 1
  • 人生,是一個不確定的命題。貧窮,富貴, 你都要面對。需要的是勇氣,需要的是擔當!更要的是人生那份責任,誰不經歷痛苦...
    秀之淵閱讀 222評論 1 0
  • 我有個姐姐,江湖人稱大玲子,大我四歲,我們經常相愛相殺,和你們分享一下我和她的日常和陳年舊事。 01 和大玲子去逛...
    水水姐姐閱讀 779評論 0 0