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;
}

 

 

 

 

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