leetcode 初级算法 数组

数组

    • 从排序数组中删除重复项
    • 买卖股票的最佳时机
    • 旋转数组
    • 存在重复
    • 只出现一次的数字
    • 两个数组的交集II
    • 加1
    • 移动0
    • 两数之和
    • 有效的数独
    • 旋转图像

从排序数组中删除重复项

题目:传入一个int型vector(已经排序),函数需要删除重复值,返回最终vector中个数。

示例:
给定数组 nums = [1,1,2],

函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。

AC代码:

class Solution {
public:
    int removeDuplicates(vector& nums) {
        int ans = 0;    //最终数组的长度
        int len = nums.size();
        for(int i = 0;i

买卖股票的最佳时机

题目:给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

例子:
输入: [7,1,5,3,6,4]
输出: 7
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。

思路:
动态规划。从后往前考虑。
最后一天在profit数组中为0,递推公式:当前考虑的下标为k,j从k+1到最后一个,如果j天的价钱高于k的,维护一个max值,为prices[j]-prices[k]+profit[j+1],最终用max更新profit[k]。注意j+1为len的情况特殊处理。

AC代码:

class Solution {
public:
    int maxProfit(vector& prices) {
        int len = prices.size();
        if(len==0) return 0;
        int profit[len];
        profit[len-1] = 0;
        for(int i = len-2;i>=0;i--)
        {
            int max = profit[i+1];
            for(int j = i+1;jprices[i])
                {
                    int temp = prices[j]-prices[i];
                    if(j!=len-1)
                        temp+=profit[j+1];
                    if(temp>max)
                        max = temp;
                }
            }
            profit[i] = max;
        }
        return profit[0];
    }
};

旋转数组

不知道哪里出错了
AddressSanitizer: heap-buffer-overflow on address 0x60200000027c at pc 0x000000406239 bp 0x7ffebdf5b5c0 sp 0x7ffebdf5b5b8

之前报错的原因:
最后一个循环里i+k也需要mod len,否则会out of bound。

AC代码:

class Solution {
public:
    void rotate(vector& nums, int k) {
        int len = nums.size();
        k = k%len;
        vector temp;
        temp.resize(len);
        //save the front values
        for(int i = 0;i=k;j--)
        {
            nums[(j+k)%len] = nums[j];
        }
         for(int i = 0;i

存在重复

题目:无重复返回false,有返回true。

AC代码:

class Solution {
public:
    bool containsDuplicate(vector& nums) {
        set s;
        for(int cur:nums)
        {
            if(s.find(cur)!=s.end())
                return true;
            s.insert(cur);
        }
        return false;
    }
};

只出现一次的数字

题目:

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

说明:

你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例 1:

输入: [2,2,1]
输出: 1
示例 2:

输入: [4,1,2,1,2]
输出: 4

solution1:
用一个set记录数字,从前到后扫描数组,第一次出现某数字时,insert;第二次时erase。最终set中唯一的就是出现两次的数字。
AC代码:

class Solution {
public:
    int singleNumber(vector& nums) {
        set ans;
        set::iterator it;
        for(int i:nums)
        {
            it = ans.find(i);
            if(it!=ans.end())
                ans.erase(it);
            else
                ans.insert(i);
        }
        return *(ans.begin());
    }
};
solution2:将传入的vector排序,从第0位开始,如果和之后的一位不等,则就是这个出现了一次,否则以步长2向后移动。
#不知道为什么没有通过
报错原因:it指向最后一个的时候,it+1会越界。
 ***错误***  代码:


   class Solution {
    public:
        int singleNumber(vector& nums) {
            sort(nums.begin(),nums.end());
            vector::iterator it;
            for(it = nums.begin();it!=nums.end();it++)
            {
                if(*it != *(it+1))
                    break;
                it += 2;
            }
            return *(it);
        }
    };
    
    AC代码:
    class Solution {
    public:
        int singleNumber(vector& nums) {
            sort(nums.begin(),nums.end());
            vector::iterator it;
            for(it = nums.begin();it!=(nums.end()-1);)
            {
                if(*it != *(it+1))
                    break;
                it += 2;
            }
            return *(it);
        }
    };

两个数组的交集II

题目:
给定两个数组,编写一个函数来计算它们的交集。

示例 1:

输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2,2]

AC代码:

class Solution {
public:
    vector intersect(vector& nums1, vector& nums2) {
        vector ans;
        sort(nums1.begin(),nums1.end());
        sort(nums2.begin(),nums2.end());
        vector::iterator it1 = nums1.begin();
        vector::iterator it2 = nums2.begin();
        while((it1!=nums1.end())&&(it2!=nums2.end()))
        {
        if((*it1)==(*it2))
        {
            ans.push_back(*it1);
            it1++;
            it2++;
        }
       else if((*it1)>(*it2))
            it2++;
        else 
            it1++;
        }
        return ans;
}
};

加1

题目:
给定的数组代表了一个非负整数,写一个+1的函数。

注意:
9999加1之后多了一位,利用vector的insert方法。

AC代码:

class Solution {
public:
    vector plusOne(vector& digits) {
        int len = digits.size();
        int i = len-1;
        while(i>=0)
        {
            digits[i]++;
            if(digits[i]!=10)
                break;
            digits[i]=0;
            i--;
        }
        if(digits[0]==0)
            digits.insert(digits.begin(),1);
        return digits;
    }
};

移动0

题目:将所有0移到数组末尾,非0保持相对顺序。

参考了别人的代码

代码:

class Solution {
public:
    void moveZeroes(vector& nums) {
        int pos = 0;
        for(int cur:nums)
        {
            if(cur!=0)
            {
                nums[pos++] = cur;
            }
        }
        for(int i = pos;i

两数之和

题目:在数组找到和为给定数字的两个数。
收获:find好像必须给出开始结尾的迭代器。
AC代码:
class Solution {
public:
vector twoSum(vector& nums, int target) {
vector ans;
vector::iterator start= nums.begin(),result,end=nums.end();
for(int i = 0;i {
result = find(start+i+1,end,target-nums[i]);
if(result!=nums.end())
{
ans.push_back(i);
ans.push_back(result-start);
return ans;
}
}
return ans;
}
};

有效的数独

//写了一个子函数检查3*3的方块

class Solution {
public:
    bool isValidSudoku(vector>& board) {
        for(int i = 0;i<9;i++)
        {
            set exist;
            for(int j = 0;j<9;j++)
            {
                char cur = board[i][j]; 
                if(cur!='.')
                {
                    if(exist.find(cur)!=exist.end())
                        return false;
                    exist.insert(cur);
                }
            }
        }
        for(int i = 0;i<9;i++)
        {
            set exist;
            for(int j = 0;j<9;j++)
            {
                char cur = board[j][i]; 
                if(cur!='.')
                {
                    if(exist.find(cur)!=exist.end())
                        return false;
                    exist.insert(cur);
                }
            }
        }
        for(int i = 0;i<9;i=i+3)
        {
            for(int j = 0;j<9;j=j+3)
            {
                if(testBlock(board,i,j)==false)
                    return false;
            }
        }
       return true; 
    }
    bool testBlock(vector>& board,int x,int y)
    {
        set exist;
         for(int i = x;i

旋转图像

模仿了别人的思路,顺时钟旋转90度,既先掉换所有对角元素,a[1][1]和a[3][3]对换(假设n=3)…然后对换列元素。
代码略

copy:
@Test
public void test() {
int[][] test1 = new int[][]{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};

 rotate(test1);
 Assert.assertArrayEquals(new int[][]{
         {7, 4, 1},
         {8, 5, 2},
         {9, 6, 3}
 }, test1);

}

public void rotate(int[][] matrix) {

 int length = matrix.length;

 // 调换对角元素
 for (int i = 0; i < length; i++) {
     for (int j = 0; j < length - i; j++) {
         int tmp = matrix[i][j];
         matrix[i][j] = matrix[length - j - 1][length - i - 1];
         matrix[length - j - 1][length - i - 1] = tmp;
     }
 }

 // 调换列元素
 for (int i = 0; i < length; i++) {
     for (int j = 0; j < length / 2; j++) {
         int tmp = matrix[j][i];
         matrix[j][i] = matrix[length - j - 1][i];
         matrix[length - j - 1][i] = tmp;
     }
 }

}
}

你可能感兴趣的:(leetcode算法题目,leetcode,算法)