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;
        }
        
    }
};
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容

  • rljs by sennchi Timeline of History Part One The Cognitiv...
    sennchi阅读 7,279评论 0 10
  • 1. Two Sum 用hash可以得到O(n)时间的解法,用python中的enumerate函数,可以获得元素...
    Morphiaaa阅读 423评论 0 0
  • 我之前暗恋一个男生,两年,很普通很普通的一个人,可我就是喜欢他。他喜欢过一段时间我闺蜜,可是我闺蜜到最后也没有答应...
    你尝一口我阅读 438评论 0 1
  • 人生,是一个不确定的命题。贫穷,富贵, 你都要面对。需要的是勇气,需要的是担当!更要的是人生那份责任,谁不经历痛苦...
    秀之渊阅读 212评论 1 0
  • 我有个姐姐,江湖人称大玲子,大我四岁,我们经常相爱相杀,和你们分享一下我和她的日常和陈年旧事。 01 和大玲子去逛...
    水水姐姐阅读 735评论 0 0