第二天-力扣刷题(例2梳理了二重for循环使用技巧)

        今天早晨复习了一下昨天的题,做的速度提高了,但是写完又报错,还找不出来为什么。感觉这样浪费时间比较多,打算调整下思路:

先直接全敲一遍,第二天复习的时候自己做,不熟练的、做错的,隔一段时间会回头重做。

例 1

题号:448, 难度:简单

题目描述:

解题思路:

数组两用,数组里存值,(下标+1)记录是否存在该数。

具体代码:

class Solution {
public:
    vector<int> findDisappearedNumbers(vector<int>& nums) {
        vector<int>ans;
        
        int n = nums.size();
        for(int i = 0; i < n; i++)  
        {
            //以值+1为索引,整个数组的索引代表数字是否存在,存在的为负数,不存在的是正数
            //特别要注意:nums[i]这个值有可能是负数,得取绝对值
            int index = abs(nums[i]) - 1;

            if(nums[index] > 0)
            {
               nums[index] = -nums[index] ;  
            }     
        }
        for(int i = 0; i < n; i++)
        {
            //找到所有为正数的索引
            if(nums[i] > 0)
            {
                ans.push_back(i + 1);
            }
        }

       return ans; 
    }
};

 运行结果:

总结:

 要注意两点:

  1. 遍历到后面有重复数的时候,读出来的值可能是负数,如果直接拿去当下标会出现问题,要取绝对值
  2. nums[index]改成nums[ abs(nums[i])  - ]的话,运行时间会增加好多。第一遍写完代码后,可以提炼一下,看看有哪些重复的地方,可以新定义一个变量然后赋值。用变量表示的话就调用函数快一些。也可能是测试的输入不同的缘故,反正代码看起来更清楚了。

例 2

题号:48, 难度:中等

题目描述:

解题思路:

先按照左上到右下对角线交换一遍,再逆置每一个数组。

具体代码:

class Solution {
public:
    void rotate(vector<vector<int>>& matrix) {
        int n = matrix.size();

        //沿左上右下对角线交换数字
        for(int i = 0; i < n ; i++)
            for(int j = i; j < n ; j++)
            {
                int temp = matrix[i][j];
                matrix[i][j] = matrix[j][i];
                matrix[j][i] = temp;
                
            }

        //每行数字反转
        for(auto &nums: matrix)
        {
            int tail = n -1;
            for(int i = 0; i < tail; i++, tail--)
            {
                int temp = nums[i];
                nums[i] = nums[tail];
                nums[tail] = temp;
            }
        }

        
    }
};

总结

1.处理技巧,剩下就是for循环的基础应用,如何把想要交换的数字交换。我这块不太熟,好好研究了一下。

假设n = 3;
最重要的点,从始至终要记牢:两重for循环过程:一行完了,下一行。
遍历范围是三角形的重点:行里元素个数不能大于列数。
for循环 第一重 可以从上到下   i = 0;    i < n;   i++;  [0,n)
              也可以从下到上 i = n - 1; i >= 0; i--;  (n,0]
        第二重 要打印三角形,限制条件一定是i,一行分成两段,[0,i) 和 [i,n)
              可以从头到尾   j = 0;     j < i;  j++;  正着的三角形 [0,i)
              也可以从尾到头 j = n - 1; j >= i; j--;  倒着的三角形 (n,i]
for循环一定要明确每重循环的功能,分开来看。一起看很容易混了。

练习1: 以下都用dev c++验证过输出的值是否正确 
 i,j:   [0,0],[   ],[   ],   
        [0,1],[1,1],[   ],
        [0,2],[1,2],[2,2],
法1:上到下,头到尾[0,i)   
    for(int i = 0; i < n; i++)
        for(int j = 0; j <= i; j++)
法2:上到下,尾到头[i,n)
    for(int i = 0; i < n; i++)
        for(int j = n - 1; j >= i; j--)
从下往上会有一些要注意的地方。
法3: 下到上,头到尾[0,i)      特别注意:因为i的初始值是n - 1, 第二重循环实际上范围是[0,i],包含i
    for(int i = n - 1; i >= 0; i--)
        for(int j = 0; j <= i; j++ )
法4: 下到上,尾到头(i,n]      特别注意:因为i的初始值是n - 1, 第二重循环实际上范围是[i,0],包含i
    for(int i = n -1; i >= 0; i--)
        for(int j = n - 1; j >= 0; j--)
思考:如果用--i的话,i初始值是否可以赋值为n
又发现一个知识点,for循环里不管是--i还是i--,循环体里的i得值不变。
但是while的话就会变。


练习2:  (在旋转数组这道题中,不管的得到的是上面部分或者下面部分都可以执行交换操作)
 i,j:   [0,0],[1,0],[2,0],                           
        [   ],[1,1],[2,1],    
        [   ],[   ],[2,2],
        
法1: 上到下,头到尾[0,i)
    for(int i = 0; i < n; i++)
        for(int j = i;  j < n; j++)

法2: 上到下,尾到头[i,n)
    for(int i = 0; i < n; i++)
        for(int j = n - 1;  j >= i; j--)

法3:  下到上,头到尾[0,i) 
    for(int i = n - 1; i >= 0; i--)
        for(int j = 0; j <= i; j++)

法4: 下到上, 尾到头[i,n)
    for(int i = n - 1; i >= 0; i--)
        for(int j = n - 1; i >= i; j--)

可以发现公式都是一样的,第一重循环i管列,第二重循环j管行里咋写。区间就是[0------i-------n)。

特殊:如果是从下到上的话,i初始值是n-1,头到尾的区间要包含i,[0-------i],[i-------n],i用了两次,i就是对角线,不管算上面的部分还是算下面的部分,斜边上的点都用到了。
    
  

题号:, 难度:

题目描述:

解题思路:

具体代码:

总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值