算法与数据结构第一周

Leetcode

66.加一

方法步骤:
数学上的加一,小时候我们列式子也是从后向前做加法的。(应该有专有名词但我忘了)
1.从后向前遍历,给当前成员加一
2.满足进位条件就置0该成员然后继续遍历,不满足则直接返回
3.当遍历结束 但没返回 表示 全进位置0的情况,则在成员前插入1即可。

class Solution  {
public:
    vector<int> plusOne(vector<int>& digits) {
        for(int i=digits.size()-1; i>=0; i--) //从后往前遍历
        {
            digits[i]++;//加一
            if(digits[i] == 10)  digits[i] = 0;//判断是否满足进位
            else  return digits;//不满足就直接返回
        }
        //如下条件举例表示 9999 + 1 = 10000
        digits.insert(digits.begin(), 1);
        //insert() 插入后将 0000 变成了 10000;
        return digits;
    }
};

算法与数据结构第一周

1.两数之和

暴力解法:两层for循环查找,时间复杂度是O(n^2)

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        int i,j;
        for(i=0;i<nums.size()-1;i++)
        {
            for(j=i+1;j<nums.size();j++)
            {
                if(nums[i]+nums[j]==target)
                {
                   return {i,j};
                }
            }
        }
        return {i,j};
    };
};

方法2:
题解来源
这个方法很明显比上面的优秀,但leetcode提交基本没差别

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        std::unordered_map <int,int> map;
        for(int i = 0; i < nums.size(); i++) {
            auto iter = map.find(target - nums[i]);
            if(iter != map.end()) {
                return {iter->second, i};
            }
            map.insert(pair<int, int>(nums[i], i));
        }
        return {};
    }
};

88.合并两个有序数组

注意考虑边界条件,如果p1 < 0,则直接将p2赋值给p,如果p2 < 0,则直接将p1赋值给p.
这个解法妙在根据 完整的已知条件 来处理问题
1.从后向前遍历,目的在于合并的同时排序(较大的数优先排在后面)
2.四种情况:①nums1为空 ②nums2为空 ③nums1成员 <= nums2成员 ④nums1成员 >= nums2成员
3.不要忘记每次情况成立后需要 自减

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        //从后向前遍历
        int p1 = m - 1 , p2 = n - 1 , p = m + n - 1;
        
        
        while(p >= 0){
            if(p1 < 0){	//如果nums1为空数组
                nums1[p] = nums2[p2--]; //nums2就为新
            }
            else if(p2 < 0){ //如果nums2为空数组
                nums1[p] = nums1[p1--]; //nums1就为新
         	} 
            else if(nums1[p1] <= nums2[p2]) { //一边排序一边合并
                nums1[p] = nums2[p2--]; //较大数在后
            }
            else{
                nums1[p] = nums1[p1--];
            }
            p--; 
        }
    }
};

26.删除排序数组中的重复项

做过移动零的会发现这道题的解法是比较类似的
快慢 双指针 来解决
快指针遍历 遇到和后一个不相同的数则去和慢指针成员交换
慢指针则是在满足条件后先自增再交换,返回值为当前下标+1,才是“长度”

注意一下快指针的结束条件,因为是第一个和第二个比较,所以需要提前一个结束。

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        if (nums.empty()) return 0; // 别忘记空数组的判断
        
        int slowIndex = 0;
        for (int fastIndex = 0; fastIndex < (nums.size() - 1); fastIndex++){
            if(nums[fastIndex] != nums[fastIndex + 1]) { // 发现和后一个不相同
                nums[++slowIndex] = nums[fastIndex + 1]; 
                //slowIndex = 0 的数据一定是不重复的,所以直接 ++slowIndex
            }
        }
        return slowIndex + 1; //别忘了slowIndex是从0开始的,所以返回slowIndex + 1
    }
};

189.旋转数组

有点难啊 我再看看怎么写 我放弃了

class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        vector<int> temp = nums;
        for (int i = 0; i < temp.size(); ++i)
            nums[(i + k) % temp.size()] = temp[i];
    }
};
上一篇:2020-01-22 数组 刷题


下一篇:17. 电话号码的字母组合 - LeetCode