1.給定一個非空整數數組,除了某個元素只出現一次以外,其餘每個元素均出現兩次。找出那個只出現了一次的元素。
輸入: [2,2,1] 輸出: 1
解:採用異或^操作,即相異才爲1,相同爲0 ,兩個相同元素相與運算後爲0 ,剩下的那一個元素與只出現了一次的元素一定不同,則異或後一定爲只出現了一次的那個值。
#include <iostream>
#include<vector>
using namespace std;
class Solution {
public:
int singleNumber(vector<int>& nums) {
int result = 0;
for (int i = 0; i < nums.size(); i++)
result ^= nums[i];//異或運算,相同爲0,不同爲1
return result;
}
};
int main()
{
Solution s1;
vector<int> a{ 3,3,5 };
cout << s1.singleNumber(a);
}
2.給定一個大小爲 n 的數組,找到其中的衆數。衆數是指在數組中出現次數大於 ⌊ n/2 ⌋
的元素。
輸入: [3,2,3] 輸出: 3
解:題目中說的衆數是出現次數大於了n/2次的,即佔了一半以上,因此可以進行一個排序,然後取中間那一個元素即爲衆數
#include <iostream>
#include<vector>
#include<algorithm>
using namespace std;
class Solution {
public:
int singleNumber(vector<int>& nums) {
sort(nums.begin(), nums.end());
return nums[nums.size() / 2];
}
};
int main()
{
Solution s1;
vector<int> a{ 3,3,5,3,1,23,4,53,2,1,1,1 ,1,1,1,1,1};
cout << s1.singleNumber(a);
}
3.編寫一個高效的算法來搜索 m x n 矩陣 matrix 中的一個目標值 target。該矩陣具有以下特性:每行的元素從左到右升序排列,
每列的元素從上到下升序排列。
示例:
現有矩陣 matrix 如下:
[ [1, 4, 7, 11, 15], [2, 5, 8, 12, 19], [3, 6, 9, 16, 22], [10, 13, 14, 17, 24], [18, 21, 23, 26, 30] ]
給定 target = 5
,返回 true
。
給定 target = 20
,返回 false
。
解:根據每行的元素從左到右升序排列,每列的元素從上到下升序排列這兩個特點可以得知右上角的元素一定是較大的,從右上角開始對target進行搜索,若target值等於右上角的值則搜索成功,若target值小於右上角,即證明target不在右上角值的所在列,則可以去掉該列。若target值大於右上角,即證明了target的值在該列的行向量裏面,轉而進行從上向下行搜索。
#include<vector>
#include<algorithm>
using namespace std;
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
if (matrix.size() == 0) {
return false;
}
int i = 0, j = matrix[0].size() - 1;
while (i < (int)matrix.size() && j >= 0)
{
if (matrix[i][j] == target)
{
return true;
}
else if (matrix[i][j] > target)
{
--j;
}
else
{
++i;
}
}
return false;
}
};
int main()
{
Solution s1;
vector<vector<int>> a{ {1,4,7,11,15},{2,5,8,12,19},{3,6,9,16,22},{10,13,14,17,24},{18,21,23,26,30} };
cout << s1.searchMatrix(a,5);
}
4. 給定兩個有序整數數組 nums1 和 nums2,將 nums2 合併到 nums1 中,使得 num1 成爲一個有序數組。
說明:
初始化 nums1 和 nums2 的元素數量分別爲 m 和 n。
你可以假設 nums1 有足夠的空間(空間大小大於或等於 m + n)來保存 nums2 中的元素。
示例:
輸入: nums1 = [1,2,3,0,0,0], m = 3 nums2 = [2,5,6], n = 3 輸出: [1,2,2,3,5,6]
解:先將nums2的元素插入到nums1中,再進行一個排序即可
#include <iostream>
#include<vector>
#include<algorithm>
using namespace std;
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int j = 0;
for (int i = m; i < m+n; i++)
{
nums1[i] = nums2[j++];
}
sort(nums1.begin(), nums1.end());
for (vector<int>::iterator it = nums1.begin(); it != nums1.end(); it++)
{
cout << (*it) << endl;
}
}
};
int main()
{
Solution s1;
vector<int> a1{ 1,2,3,0,0,0 }, a2{ 2,5,6 };
s1.merge(a1,3,a2,3);
}
5.你將獲得 K
個雞蛋,並可以使用一棟從 1
到 N
共有 N
層樓的建築。每個蛋的功能都是一樣的,如果一個蛋碎了,你就不能再把它掉下去。你知道存在樓層 F
,滿足 0 <= F <= N
任何從高於 F
的樓層落下的雞蛋都會碎,從 F
樓層或比它低的樓層落下的雞蛋都不會破。每次移動,你可以取一個雞蛋(如果你有完整的雞蛋)並把它從任一樓層 X
扔下(滿足 1 <= X <= N
)。你的目標是確切地知道 F
的值是多少。無論 F
的初始值如何,你確定 F
的值的最小移動次數是多少?
示例 1:
輸入:K = 1, N = 2 輸出:2 解釋: 雞蛋從 1 樓掉落。如果它碎了,我們肯定知道 F = 0 。 否則,雞蛋從 2 樓掉落。如果它碎了,我們肯定知道 F = 1 。 如果它沒碎,那麼我們肯定知道 F = 2 。 因此,在最壞的情況下我們需要移動 2 次以確定 F 是多少。
示例 2:
輸入:K = 2, N = 6 輸出:3
解:
假設我們第一個雞蛋扔出的位置在第X層(1<=X<=M),會出現兩種情況:
1.第一個雞蛋沒碎
那麼剩餘的M-X層樓,剩餘N個雞蛋,可以轉變爲下面的函數:
F(M-X,N)+ 1,1<=X<=M
2.第一個雞蛋碎了
那麼只剩下從1層到X-1層樓需要嘗試,剩餘的雞蛋數量是N-1,可以轉變爲下面的函數:
F(X-1,N-1) + 1,1<=X<=M
整體而言,我們要求出的是 N層樓 / K個雞蛋 條件下,最大嘗試次數最小的解,所以這個題目的狀態轉移方程式如下:
X可以爲1......N,所以有M個Max( F(N-X,K)+ 1, F(X-1,K-1) + 1)的值,最終F(N,K)是這M個值中的最小值,即最優解
F(N,K)= Min(Max( F(N-X,K)+ 1, F(X-1,K-1) + 1)),1<=X<=N
我們使用record數組來記錄最多檢測的樓層數,move代表移動次數,K代表雞蛋個數,N代表樓層數。即設函數:
層數n=黑箱子fun函數f(x,k)表示移動x次,k個雞蛋能夠檢測到的最高層數。
假設從n0+1層上扔下一個雞蛋:
1.若雞蛋碎了,則剩下x-1次機會和k-1個雞蛋來檢測n0層樓
2.若雞蛋沒有碎,則剩下x-1次機會和k個雞蛋來檢測n1層樓.即通過x-1次機會可以檢測出1到n0+n1+1樓層的範圍。
用函數表示:
狀態轉移方程:f(x,k) = f(x-1,k-1)+f(x-1,k)+1
即:本次fun(k)檢測的樓層數=上次fun(k-1)雞蛋碎掉情況下檢測的樓層數+上次fun(k)雞蛋沒有碎掉情況下檢測的樓層數+1,1代表本次加了一層樓層來進行檢測。
算法思想:移動了move次後,能夠檢測到的最大樓層數超過給定的樓層數則跳出循環,返回move值,否則利用狀態轉移方程進行樓層數累加統計。
#include <iostream>
#include<vector>
using namespace std;
class Solution {
public:
int superEggDrop(int K, int N) {
//record[i]=n表示第i個雞蛋經過moves的移動,最多檢測到的層數
vector<int>record(K + 1, 0);//包含0個雞蛋的情況,所以需要申請K+1個空間
int move = 0;
while (record[K] < N)//當record[K]大於等於N的時候就退出循環
{
for (int i = K; i >= 1; i--)
/*假設record[k-1]=n0,record[k]=n1,
首先檢測,從第 n0+1 樓丟下雞蛋會不會破。
如果雞蛋破了,F 一定是在 [1:n0] 樓中,利用剩下的 moves-1 次機會和 k-1 個雞蛋,可以把 F 找出來.
如果雞蛋沒破,假如 F 在 [n0+2:n0+n1+1] 樓中,利用剩下的 moves-1 次機會和 k 個雞蛋,也可以把 F 找出來。
所以,當有 moves 個放置機會和 k 個雞蛋的時候,F 在 [1, n0+n1+1] 中的任何一樓,都能夠被檢測出來。*/
record[i] += record[i - 1] + 1;
move++;
}
return move;//返回需要的嘗試次數
}
};
int main()
{
Solution s1;
cout<<s1.superEggDrop(2,3);
}