leetcode刷题——数组

一、二分查找

1.leetcode704(简单)

题目链接:https://leetcode-cn.com/problems/binary-search/

解题思路:题目已知条件是有序,所以考虑二分查找。

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

2.leetcode35搜索插入位置(简单)

题目链接:力扣

方法1:暴力解法。时间复杂度O(n),空间复杂度O(1)。

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

方法2:二分查找法。时间复杂度O(logn),空间复杂度O(1)。

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

3.leetcode34在排序数组中查找元素的第一个位置和最后一个位置(中等)

题目链接:力扣

解法1:利用二分查找。时间复杂度O(logn),空间复杂度O(1).

主要是找第一个=target的位置和第一个大于target的位置。

#include
#include 
using namespace std;

class Solution {
public:
    //查找第一个等于target的下标
    int binarySearch_equal(vector& nums, int target)
    {
        int left = 0;
        int right = nums.size() - 1;
        int ans = nums.size();
        while (left <= right)
        {
            int mid = left + (right - left) / 2;
            if (target <= nums[mid])
            {
                ans = mid;
                right = mid - 1;
            }
            else
            {
                left = mid + 1;
            }
        }
        return ans;
    }
    int binarySearch_greater(vector& nums, int target)
    {
        int left = 0;
        int right = nums.size() - 1;
        int ans = nums.size();
        while (left <= right)
        {
            int mid = left + (right - left) / 2;
            if (target < nums[mid])
            {
                ans = mid;
                right = mid - 1;
            }
            else
            {
                left = mid + 1;
            }
        }
        return ans;
    }
    vector searchRange(vector& nums, int target) {
       if (nums.empty() ||target < nums[0] || target > nums[nums.size()-1]) 
            return vector{-1,-1};
        else{
        int left_val = binarySearch_equal(nums, target);
        int right_val = binarySearch_greater(nums, target)-1;
        if(left_val <= right_val)
            return vector{left_val, right_val};
        else
            return vector{-1,-1};
    }
    }
};

解法2:利用STL现成的函数。

class Solution {
public:
    vector searchRange(vector& nums, int target) {
        vector::iterator it = find(nums.begin(),nums.end(),target);
        int left = -1;
        int right = -1;
        if(it != nums.end())
        {
            left = it-nums.begin();
            int num = count(nums.begin(),nums.end(),target);
            right = left+num-1;
        }
        return vector{left,right};
    }
};

4.leetcode69x的平方根(简单)

题目链接:力扣

解法:二分查找。

易错点:注意数的范围,mid*mid可能为long long。

class Solution {
public:
    int mySqrt(int x) {
        int left = 0;
        int right = x;
        int ret = -1;
        while (left <= right)
        {
            int mid = left + (right - left) / 2;
            if ((long long)mid * mid <= x)
            {
                ret = mid;
                left = mid + 1;
            }
            else
            {
                right = mid - 1;
            }
        }
        return ret;
    }
};

5.leetcode367有效的完全平方数(简单)

题目链接:力扣

解法:二分查找法


class Solution {
public:
    bool isPerfectSquare(int num) {
        int left = 0;
        int right = num;
        while (left <= right)
        {
            int mid = left + (right - left) / 2;
            if ((long long)mid * mid == num)
            {
                return true;
            }
            else if ((long long)mid * mid > num)
            {
                right = mid - 1;
            }
            else
            {
                left = mid + 1;
            }
        }
        return false;
    }
};

总结:

寻找刚好相等的的话,直接返回mid;如果像是34或者367一样,等于条件与另一个条件混合在一起的话,设置一个变量ret记录,然后返回。

二、移除元素

1.leetcode27移除元素(简单)

题目链接:力扣

解法:双指针法。


class Solution {
public:
    int removeElement(vector& nums, int val) {
        int slow = 0;
        for (int fast = 0;fast < nums.size();fast++)
        {
            if (nums[fast] != val)
            {
                nums[slow++] = nums[fast];
            }
        }
        return slow;
    }
};

2.leetcode26删除有序数组中的重复元素(简单)

题目链接:力扣

解法一:利用双指针法。


class Solution {
public:
    int removeDuplicates(vector& nums) {
        int slow = 0;
        for (int fast = 0;fast < nums.size();fast++)
        {
            if (fast== 0 ||nums[fast] != nums[fast-1])
            {
                nums[slow++] = nums[fast];
            }
        }
        return slow;
    }
};

解法二:利用STL中的erase函数。

class Solution {
public:
    int removeDuplicates(vector& nums) {

        for(int i = 0;i < nums.size();i++)
        {
            if(i >0 &&(nums[i] == nums[i-1]))
            {
               nums.erase(nums.begin()+i);
                 i--;
            }
        }
        return nums.size();
    }
};

解法三:利用STL中的去重函数unique。

class Solution {
public:
    int removeDuplicates(vector& nums) {
        return unique(nums.begin(),nums.end())-nums.begin();
    }
};

总结:unique函数原型

unique函数的函数原型如下:只有两个参数,且参数类型都是迭代器:

1

iterator unique(iterator it_1,iterator it_2);

这种类型的unique函数是我们最常用的形式。其中这两个参数表示对容器中[it_1,it_2)范围的元素进行去重(注:区间是前闭后开,即不包含it_2所指的元素),返回值是一个迭代器,它指向的是去重后容器中不重复序列的最后一个元素的下一个元素

3.leetcode844比较含退格的字符串(简单)

题目链接:

力扣

解法一:双指针法。时间复杂度O(N+M)。空间复杂度O(1)。


//双指针
class Solution {
public:
    bool backspaceCompare(string s, string t) {
        int i = s.size() - 1;
        int j = t.size() - 1;
        int sskipNum = 0;
        int tskipNum = 0;
        while (1)
        {
            while (i >= 0)
            {
                if (s[i] == '#')
                {
                    sskipNum++;
                }
                else
                {
                    if (sskipNum > 0)
                    {
                        sskipNum--;
                    }
                    else
                    {
                        break;
                    }
                }
                i--;
            }
            while (j >= 0)
            {
                if (t[j] == '#')
                {
                    tskipNum++;
                }
                else
                {
                    if (tskipNum > 0)
                    {
                        tskipNum--;
                    }
                    else
                    {
                        break;
                    }
                }
                j--;
            }
            if (i < 0 || j < 0) break;
            if (s[i] != t[j]) return false;
            i--;
            j--;
        }
        if (i == -1 && j == -1)
        {
            return true;
        }
        return false;
    }
};

解法二:重构字符串法。时间复杂度O(N+M)。空间复杂度O(N+M)。

//重构字符串
class Solution {
public:
    bool backspaceCompare(string s, string t) {
        return build(s) == build(t);
    }
    string build(string str)
    {
        string ret;
        for (char ch : str)
        {
            if (ch != '#')
            {
                ret.push_back(ch);
            }
            else if(!ret.empty())
            {
                ret.pop_back();
            }
        }
         return ret;
    }
};

4.leetcode977有序数组的平方(简单)

题目链接:力扣

解法一:双指针法。时间复杂度:O(n),空间复杂度O(1)。

#include 
#include
using namespace std;
class Solution {
public:
    vector sortedSquares(vector& nums) {
        int i, j,k;
        k = nums.size() - 1;
        vector result(nums.size(), 0);
        for (i = 0, j = nums.size() - 1;i <= j;)
        {
            if (nums[i] * nums[i] > nums[j] * nums[j])
            {
                result[k--] = (nums[i] * nums[i]);
                i++;
            }
            else
            {
                result[k--]=(nums[j] * nums[j]);
                j--;
            }
        }
        return result;
    }
};

解法2:暴力解法。stl中的内置函数sort。空间复杂度:O(n+nlogn)。空间复杂度:O(logn)。

class Solution {
public:
    vector sortedSquares(vector& nums) {
        for (int i = 0;i < nums.size();i++)
        {
           nums[i]*=nums[i];
        }
        sort(nums.begin(), nums.end());
        return nums;
    }
};

注意:STL中的sort函数的时间复杂度是O(nlogn)。

三、滑动窗口

1.leetcode209长度最小的子数组。(中等)

题目连接:力扣

解法一:暴力解法。时间复杂度O(n^2),空间复杂度O(1)。

#include 
#include
using namespace std;
//暴力解法
class Solution {
public:
    int minSubArrayLen(int target, vector& nums) {
        int result = 65535;
        int sublength = 0; //子序列长度
        for (int i = 0;i < nums.size();i++)
        {
            int sum = 0;
            for (int j = i;j < nums.size();j++)
            {
                sum += nums[j];
                if (sum >= target)
                {
                    sublength = j - i + 1;
                    result = result < sublength ? result : sublength;
                    break;
                }
            }
        }
        return result == 65535? 0 : result;
    }
};

解法二:滑动窗口——双指针。时间复杂度O(n),空间复杂度O(1) .

//滑动窗口——双指针
class Solution {
public:
    int minSubArrayLen(int target, vector& nums) {
        int start = 0;
        int end;
        int sum = 0;
        int result = 65535;
        int sublength = 0;
        for (end = 0;end < nums.size();end++)
        {
            sum += nums[end];
            while (sum >= target)
            {
                sublength = end - start + 1;
                result = result < sublength ? result : sublength;
                sum -= nums[start++];

            }

        }
        return result == 65535 ? 0 : result;
    }
};

2.leetcode904水果成篮(中等)

题目链接:力扣

解法:滑动窗口

备注:写了很久。。。

#include
#include
#include 
using namespace std;

class Solution {
public:
    int totalFruit(vector& fruits) {
        map basket;
        int i = 0;
        int result = 0;
        for (int j = 0;j < fruits.size();++j)
        {
            basket.insert(pair(fruits[j], ++basket[fruits[j]]));
            while (basket.size() > 2)
            {
                --basket[fruits[i]];
                if(basket[fruits[i]] == 0)
                    basket.erase(fruits[i]);
                i++;
            }
            result = result > (j - i + 1) ? result : (j - i + 1);
        }
        return result;
    }
};

3.leetcode76最小覆盖子串(困难)

题目链接:力扣  

解法:滑动窗口+哈希表

class Solution {
public:
    string minWindow(string s, string t) {
        vector need(128, 0);
        for (char ch:t)
        {
            need[ch]++;
        }
        int left = 0, right = 0,count = t.size(), result = 65535,start = 0;
        while (right < s.size())
        {
            if (need[s[right]] > 0)
            {
                count--;   
            }
            need[s[right]]--;
            if(count == 0)
            {
                while (left < right && need[s[left]] < 0)
                {
                    need[s[left++]]++;
                }
                if (right - left + 1 < result)
                {
                    result = right - left + 1;
                    start = left;
                }
                need[s[left]]++;
                left++;
                count++;
            }
            right++;
        }
        if(result == 65535)
        {
            return "";
        }
        else
        return s.substr(start, result);
    }
};

注意:

1.在leetcode中解决问题时,所有声明的变量必须在类内。不然会出现测试可以通过,而提交不通过的情况。这次因为把vector在solution类外声明耗费了大量时间找错。

2.substr函数的第二个参数是指要截取的长度。

四、螺旋矩阵

1.leetcode59螺旋矩阵II(中等)

题目链接:力扣

解法:模拟

#include
#include 
using namespace std;
class Solution {
public:
    vector> generateMatrix(int n) {
        vector> result(n, vector(n));
        int k = 1;
        int left = 0, right = n - 1, top = 0, bottom = n - 1;
        while (k <= n * n)
        {
            for (int i = left;i <= right;i++, k++)
            {
                result[top][i] = k;
            }
            top++;
            for (int i = top;i <= bottom;i++, k++)
            {
                result[i][right] = k;
            }
            right--;
            for (int i = right;i >= left;i--, k++)
            {
                result[bottom][i] = k;
            }
            bottom--;
            for (int i = bottom;i >= top;i--, k++)
            {
                result[i][left] = k;
            }
            left++;
        }
        return result;
    }
};

2.leetcode 54螺旋矩阵(中等)

题目链接:力扣

解法:模拟

#include
#include
using namespace std;
class Solution {
public:
    vector spiralOrder(vector>& matrix) {
        int rows = matrix.size();
        int columns = matrix[0].size();
        int count = rows * columns;
        vector res;
        int k = 0,left = 0, right = columns - 1, top = 0, bottom = rows - 1;
        while (k < count)
        {
            for (int i = left;i <= right&&k < count;++i)
            {
                res.push_back(matrix[top][i]);
                k++;
            }
            top++;
            for (int i = top;i <= bottom&&k < count;++i)
            {
                res.push_back(matrix[i][right]);
                k++;
            }
            right--;
            for (int i = right;i >= left&&k < count;--i)
            {
                res.push_back(matrix[bottom][i]);
                k++;
            }
            bottom--;
            for (int i = bottom;i >= top&&k < count;--i)
            {
                res.push_back(matrix[i][left]);
                k++;
            }
            left++;
        }
        return res;
    }
};

3.leetcode剑指offer29顺时针打印矩阵(简单)

题目链接:力扣

解法:模拟(与上题相同)


class Solution {
public:
    vector spiralOrder(vector>& matrix) {
        if (matrix.size() == 0 || matrix[0].size() == 0) {
            return {};
        }
        vector res;
        int rows = matrix.size();
        int columns = matrix[0].size();
        int count = rows * columns;
        int left = 0, right = columns - 1, top = 0, bottom = rows - 1, k = 0;
        while (k < count)
        {
            for (int i = left;i <= right&&k= left&&k < count ;--i)
            {
                res.push_back(matrix[bottom][i]);
                k++;
            }
            bottom--;
            for (int i = bottom;i >= top && k < count;--i)
            {
                res.push_back(matrix[i][left]);
                k++;
            }
            left++;
        }
        return res;
    }
};

注意:

需要考虑输入数组为空的情况。判断二维数组为空条件是行数为0或者列数为0且返回空数组的写法是:return {};上题虽然也能通过,但也需要补充这个条件。

其他题目

1.leetcode1365有多少少于当前数字的数字。(学会计数排序)

你可能感兴趣的:(数据结构与算法,leetcode,算法,职场和发展)