3.力扣2018年常见编程题总结(数组)

1.给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数)。

示例 1:

输入: [2,3,-2,4] 输出: 6

解释: 子数组 [2,3] 有最大乘积 6。

示例 2:

输入: [-2,0,-1] 输出: 0 解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。

解:因为是寻找连续的最大乘积,因此想到使用for循环来记录每一层的最大值,这里需要注意的是两个负数相乘仍为正数,因此需要用两个数组了记录每次连乘后的结果。一个始终记录最大的,一个始终记录最小的乘积结果。

代码:

#include <iostream>
using namespace std;

class Solution {
public:
	int maxProduct(vector<int>& nums) {
		int len = nums.size();
		int *max_arr = (int *)calloc(len, sizeof(int));
		int *min_arr = (int *)calloc(len, sizeof(int));
		max_arr[0] = nums[0];
		min_arr[0] = nums[0];
		int max_num = 0;
		for (int i = 1; i < len; i++)
		{
			max_arr[i] = max(max(max_arr[i-1]*nums[i], min_arr[i - 1] * nums[i]), nums[i]);
			min_arr[i] = min(min(max_arr[i-1]*nums[i], min_arr[i - 1] * nums[i]),nums[i]);
			max_num = max(max(max_arr[i], min_arr[i]), max_num);
		}
		return max_num;
	}
	int max(int a, int b)
	{
		return a > b ? a : b;
	}
	int min(int a, int b)
	{
		return a < b ? a : b;
	}
};

int main()
{
	Solution s1;
	vector<int> a = { 0,20 };
	cout << s1.maxProduct(a);
	return 1;
}

2.给定一个大小为 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。你可以假设数组是非空的,并且给定的数组总是存在众数。

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

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

解:因为众数大于了总数的一半,因此可以采用排序来进行取中间索引得到中间的数即为众数

代码:

#include<algorithm>
#include<iostream>
class Solution {
public:
    int majorityElement(vector<int>& nums) {
        sort(nums.begin(), nums.end());
		return nums[nums.size() / 2];
    }
};

3.给定一个数组,将数组中的元素向右移动 个位置,其中 是非负数。

示例 1:输入: [1,2,3,4,5,6,7]k = 3 输出: [5,6,7,1,2,3,4]

解释: 向右旋转 1 步: [7,1,2,3,4,5,6] 向右旋转 2 步: [6,7,1,2,3,4,5] 向右旋转 3 步: [5,6,7,1,2,3,4]

代码:

#include <iostream>
using namespace std;

class Solution {
public:
	void rotate(vector<int>& nums, int k) {
		k = k % nums.size();
		for (int i = 0; i < nums.size() / 2; i++)
			swap(nums[i], nums[nums.size() - 1 - i]);
		for (int j = 0; j < k / 2; j++)
			swap(nums[j], nums[k - 1 - j]);
		for (int m = k; m < (nums.size() + k) / 2; m++)
			swap(nums[m], nums[nums.size() - 1 - m + k]);
    }
};

int main()
{
	Solution s1;
	vector<int> a = { 1,3,5,7,9 };
	s1.rotate(a,3);
	return 1;
}

4.给定一个整数数组,判断是否存在重复元素。如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。

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

解:因为要判断的数据中可能有负数,因此不能采用散列表的形式,可以采用排序的方式,先将数据进行排序,之后遍历一次查看前后的元素是否一样。

代码:

class Solution {
public:
	bool containsDuplicate(vector<int>& nums) {
		int len = nums.size();
		sort(nums.begin(), nums.end());
		for (int i = 1; i < len; i++)
		{
			if (nums[i - 1] == nums[i])
				return 1;
		}
		return 0;
	}
};

int main()
{
	Solution s1;
	vector<int> a = { 1,5,-2,-4,0,5};
	cout<<s1.containsDuplicate(a);
	return 1;
}

5.给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

示例:输入: [0,1,0,3,12] 输出: [1,3,12,0,0]

解:先将非零元素按顺序重新赋值到前面的数组中,后面的数组手动赋值0

代码:

class Solution {
public:
	void moveZeroes(vector<int>& nums) {
		int len = nums.size();
		int j=0;
		for (int i = 0; i < len; i++)
		{
			if (nums[i]!=0)
			{
				nums[j++] = nums[i];
			}
		}
		for (int i = j; i < len; i++)
		{
			nums[i] = 0;
		}
		for  (vector<int>::iterator i = nums.begin();i<nums.end();i++)
		{
			cout << *i << endl;
		}
	}
};

int main()
{
	Solution s1;
	vector<int> a = { 0,0,5};
	s1.moveZeroes(a);
	return 1;
}

6.打乱一个没有重复元素的数组。

例:int[] nums = {1,2,3};

Solution solution = new Solution(nums);

// 打乱数组 [1,2,3] 并返回结果。任何 [1,2,3]的排列返回的概率应该相同。

solution.shuffle();

// 重设数组到它的初始状态[1,2,3]。

solution.reset();

// 随机返回数组[1,2,3]打乱后的结果。

solution.shuffle();

解:构造函数相当于对vector进行拷贝一份,用于reset的恢复,shuffle函数中通过rand产生一个随机位置,然后进当前位置与随机位置的数据交换

代码:

using namespace std;

class Solution {
public:
	Solution(vector<int>& nums) {
		temp = nums;
	}

	/** Resets the array to its original configuration and return it. */
	vector<int> reset() {
		return temp;
	}

	/** Returns a random shuffling of the array. */
	vector<int> shuffle() {
		vector<int> cur(temp);
		for (int i = 0; i <cur.size() ; i++)
		{
			int pos = rand() % (i + 1);
			int t = cur[i];
			cur[i] = cur[pos];
			cur[pos] = t;
		}
		return cur;
	}

private: vector<int> temp;
};

int main()
{
	vector<int> a = { 2,3,5},b;
	Solution s1(a);
	b = s1.shuffle();
	for (vector<int>::iterator i = b.begin(); i < b.end(); i++)
		cout << *i << endl;
	return 1;
}

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

示例 1:输入: nums1 = [1,2,2,1], nums2 = [2,2]

输出: [2,2]

解:求交集中可能有重复元素,所以不能使用set来完成,可以将两个数组排序后利用vector弹出一个一个 的数据来进行比较。

代码:

using namespace std;

class Solution {
public:
	vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
		vector<int> intersection;
		int len1 = nums1.size();
		int len2 = nums2.size();
		sort(nums1.begin(), nums1.end());
		sort(nums2.begin(), nums2.end());
		while (nums1.size()&&(nums2.size()))
		{
			if (nums1[len1 -1] > nums2[len2-1])
			{
				nums1.pop_back();
				--len1;
			}
			else if (nums1[len1 - 1] == nums2[len2 - 1])
			{
				intersection.push_back(nums1[len1 - 1]);
				nums1.pop_back();
				nums2.pop_back();
				--len1;
				--len2;
			}
			else if (nums1[len1 - 1] < nums2[len2 - 1])
			{
				nums2.pop_back();
				--len2;
			}
		}
		return intersection;
	}
};

int main()
{
	vector<int> a = { 4,9,5 }, b = { 9,4,9,8,4 },c;
	Solution s1;
	c = s1.intersect(a, b);
	for (vector<int>::iterator i = c.begin(); i < c.end(); i++)
		cout << *i << endl;
	return 1;
}

8.给定一个未排序的数组,判断这个数组中是否存在长度为 3 的递增子序列。

数学表达式如下:

如果存在这样的 i, j, k,  且满足 0 ≤ i < j < k ≤ n-1,
使得 arr[i] < arr[j] < arr[k] ,返回 true ; 否则返回 false 。

说明: 要求算法的时间复杂度为 O(n),空间复杂度为 O(1) 。

示例 1:输入: [1,2,3,4,5] 输出: true

解:因为是对任意位置进行递增序列的寻找,因此需要两个变量来记录前面两个的最小值,若当前的元素大于前面记录的两个最小值,则代表该数组是递增子序列。

代码:

using namespace std;

class Solution {
public:
	bool increasingTriplet(vector<int>& nums) {
		bool increasingTriplet(vector<int>& nums) {
			if (nums.size() < 3)
				return false;
			int c1 = INT_MAX;
			int c2 = INT_MAX;
			for (int i = 0; i < nums.size(); i++) {
				if (nums[i] <= c1) {
					c1 = nums[i];
				}
				else if (nums[i] <= c2) {
					c2 = nums[i];
				}
				else {
					return true;
				}
			}
			return false;
		}
};

int main()
{
	vector<int> b = { 5,1,2,3,5 };
	Solution s1;
	cout<< s1.increasingTriplet( b);
	return 1;
}

9.给定长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。

示例:输入: [1,2,3,4] 输出: [24,12,8,6]

解:先存储左边的累计乘法结果,再存储右边的结果。

代码:

using namespace std;

class Solution {
public:
	vector<int> productExceptSelf(vector<int>& nums) {
		int len = nums.size();
		vector<int> output(len, 1);
		for (int i = 1; i < len; i++)//存储i左边的乘积之和
			output[i] = output[i - 1] * nums[i - 1];
		int right = 1;
		for (int i = len - 1; i >= 0; i--)//i右边的乘积之和
		{
			output[i] *= right;
			right *= nums[i];
		}
		return output;
	}
};

int main()
{
	vector<int> b = { 5,1,2,3,5 };
	Solution s1;
	b=s1.productExceptSelf( b);
	return 1;
}

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章