目錄
1.best-time-to-buy-and-sell-stock
2.best-time-to-buy-and-sell-stock-ii
3.best-time-to-buy-and-sell-stock-iii
5.remove-duplicates-from-sorted-array
6.remove-duplicates-from-sorted-array-ii
8.convert-sorted-array-to-binary-search-tree
1.best-time-to-buy-and-sell-stock
題目:假設你有一個數組,其中第i個元素是某隻股票在第i天的價格。如果你最多隻能完成一筆交易(即買一股和賣一股股票),設計一個算法來求最大利潤。
分析:見劍指offer面試題63 https://blog.csdn.net/Nibaby9/article/details/104126765
2.best-time-to-buy-and-sell-stock-ii
題目:假設你有一個數組,其中第i個元素表示某隻股票在第i天的價格。設計一個算法來尋找最大的利潤。你可以完成任意數量 的交易(例如,多次購買和出售股票的一股)。但是,你不能同時進行多個交易(即,你必須在再次購買之前賣出之前買的股票)。
分析:貪心法,相鄰兩天的股票價格只要是遞增,利潤就會加大。
public int maxProfit(int[] prices) {
if(prices == null || prices.length == 0)
return 0;
int max_profit = 0;
for(int i = 1;i < prices.length;i++){
if(prices[i] - prices[i-1] > 0)
max_profit += prices[i] - prices[i-1];
}
return max_profit;
}
3.best-time-to-buy-and-sell-stock-iii
題目:假設你有一個數組,其中第i個元素是某隻股票在第i天的價格。設計一個算法來求最大的利潤。你最多可以進行兩次交易。注意:你不能同時進行多個交易(即,你必須在再次購買之前出售之前買的股票)。
分析:貪心法。無論是買還是賣,模擬兩次買和賣,都取利潤的最大值即可。
public int maxProfit(int[] prices) {
if(prices == null || prices.length == 0)
return 0;
int buy1 = Integer.MIN_VALUE,sell1 = 0,buy2 = Integer.MIN_VALUE,sell2 = 0;
for(int i = 0;i < prices.length;i++){
buy1 = Math.max(buy1,-prices[i]);//第一次買股票的利潤
sell1 = Math.max(sell1,prices[i] + buy1);//第一次賣股票後所盈利的
buy2 = Math.max(buy2,sell1 - prices[i]);//第二次買股票後的利潤:第一次的利潤 - 股票錢
sell2 = Math.max(sell2,prices[i] + buy2);
}
return sell2;
}
4.first-missing-positive
題目:給出一個無序的整數型數組,求不在給定數組裏的最小的正整數。例如:給出的數組爲[1,2,0] 返回3,給出的數組爲[3,4,-1,1] 返回2.你需要給出時間複雜度在O(n)之內並且空間複雜度爲常數級的算法。
分析:數組下標從0開始,讓數組中滿足大於0和小於數組長度的數都滿足a[i]==i+1(注意:不能直接用A[i] != i+1來作爲循環條件,因爲有可能數組中根本i+1這個數),最後再遍歷數組第一個不滿足a[i]==i+1的就是缺失的最小正整數。
public int firstMissingPositive(int[] A) {
for(int i = 0;i < A.length;i++){
while(A[i] > 0 && A[i] <= A.length && A[i] != A[A[i]-1]){
int temp = A[A[i]-1];A[A[i]-1] = A[i];A[i] = temp;//swap(A[i],A[A[i]-1]);
}
}
for(int i = 0;i < A.length;i++){
if(A[i] != i+1)
return i+1;
}
return A.length + 1;
}
5.remove-duplicates-from-sorted-array
題目:給定一個已排序的數組,使用就地算法將重複的數字移除,使數組中的每個元素只出現一次,返回新數組的長度。不能爲數組分配額外的空間,你必須使用常熟級空間複雜度的就地算法。例如,給定輸入數組 A=[1,1,2],你給出的函數應該返回length=2,A數組現在是[1,2]。
分析:用len來標記數組當前加入非重複數字的有效長度即可。
public int removeDuplicates(int[] A) {
if(A.length == 0)
return 0;
int len = 0;
for(int i = 1;i < A.length;i++){
if(A[i] != A[i-1])
A[++len] = A[i];
}
return len+1;
}
6.remove-duplicates-from-sorted-array-ii
題目:繼續思考題目"Remove Duplicates":如果數組中元素最多允許重複兩次呢?例如:給出有序數組 A =[1,1,1,2,2,3],你給出的函數應該返回length =5, A 變爲[1,1,2,2,3].
分析:在上題的基礎上,多加一個flag來標誌某元素重複的次數即可。
public int removeDuplicates(int[] A) {
if(A == null || A.length == 0)
return 0;
int len = 1,flag = 1;
for(int i = 1;i < A.length;i++){
if(A[i] != A[i-1]){
A[len++] = A[i];
flag = 1;
}
else if(flag == 1){
flag++;
A[len++] = A[i];
}
}
return len;
}
7.merge-sorted-array
題目:給出兩個有序的整數數組A和B,請將數組B合併到數組A中,變成一個有序的數組。注意:可以假設A數組有足夠的空間存放B數組的元素,A和B中初始的元素數目分別爲m和n
分析:將數從後往前依次放入即可。
public void merge(int A[], int m, int B[], int n) {
int i = m-1,j = n-1,x = m + n -1;
while(i >= 0 && j >= 0){
if(A[i] > B[j])
A[x] = A[i--];
else
A[x] = B[j--];
x--;
}
while(j >= 0)
A[x--] = B[j--];
}
8.convert-sorted-array-to-binary-search-tree
題目:給出一個升序排序的數組,將其轉化爲平衡二叉搜索樹(BST).
分析:找中間結點mid = (left + right)/2作爲根結點,遞歸求出左右子樹即可。出口易錯!!!
public TreeNode sortedArrayToBST(int[] num) {
if(num == null || num.length == 0)
return null;
return toBST(num,0,num.length);
}
private TreeNode toBST(int[] num, int left, int right) {
if(left >= right ) //易錯
return null;
int mid = (left + right) / 2;
TreeNode root = new TreeNode(num[mid]);
root.left = toBST(num,left,mid);
root.right = toBST(num,mid+1,right);
return root;
}
9.two-sum
題目:給出一個整數數組,請在數組中找出兩個加起來等於目標值的數,你給出的函數twoSum 需要返回這兩個數字的下標(index1,index2),需要滿足 index1 小於index2.。注意:下標是從1開始的,假設給出的數組中只存在唯一解。例如:給出的數組爲 {2, 7, 11, 15},目標值爲9,輸出 ndex1=1, index2=2。
分析:用HashMap來存儲每個數字的下標即可。
若數組已排好序,參見劍指offer面試題57 https://blog.csdn.net/Nibaby9/article/details/104126811
public int[] twoSum(int[] numbers, int target) {
int [] re = new int[2];
HashMap<Integer,Integer> map = new HashMap<>();
for(int i = 0;i < numbers.length;i++){
if(map.containsKey(target - numbers[i])){
re[0] = map.get(target - numbers[i]);
re[1] = i + 1;
return re;
}
else{
map.put(numbers[i],i+1);
}
}
return re;
}
10.3sum
題目:給出一個有n個元素的數組S,S中是否有元素a,b,c滿足a+b+c=0?找出數組S中所有滿足條件的三元組。注意:三元組(a、b、c)中的元素必須按非降序排列。(即a≤b≤c);解集中不能包含重複的三元組。 例如,給定的數組 S = {-1 0 1 2 -1 -4},↵↵ 解集爲:↵ (-1, 0, 1)↵ (-1, -1, 2)
分析:先對數組排好序,然後固定第一個數字,就可以將問題轉化爲查找兩個數爲目標值。但是需特別注意去重問題!!!
public ArrayList<ArrayList<Integer>> threeSum(int[] num) {
ArrayList<ArrayList<Integer>> res = new ArrayList<>();
if(num.length < 3)
return res;
Arrays.sort(num);
for(int i = 0;i < num.length - 2;i++){
if(num[i] + num[i+1] + num[i+2] > 0)
return res;
if(i > 0 && num[i] == num[i-1])
continue;
if(num[i] + num[num.length - 1] + num[num.length - 2] < 0)
continue;
int low = i + 1;
int high = num.length - 1;
while(low < high){
if(num[i] + num[low] + num[high] == 0){
ArrayList<Integer> list = new ArrayList<>();
list.add(num[i]);list.add(num[low]);list.add(num[high]);
res.add(list);
low++;high--;
while(low < high && num[low] == num[low-1])
low++;
while(low < high && num[high] == num[high+1])
high--;
}
else if(num[i] + num[low] + num[high] > 0)
high--;
else
low++;
}
}
return res;
}
11.3sum-closest
題目:給出含有n個整數的數組s,找出s中和加起來的和最接近給定的目標值的三個整數。返回這三個整數的和。你可以假設每個輸入都只有唯一解。 例如,給定的整數 S = {-1 2 1 -4}, 目標值 = 1.↵↵ 最接近目標值的和爲 2. (-1 + 2 + 1 = 2).
分析:跟上題思想一樣,只是在計算的過程中需記錄離目標值最接近的值。
public int threeSumClosest(int[] num, int target){
if(num.length < 3)
return 0;
Arrays.sort(num);
int res = num[0] + num[1] + num[2];
for(int i = 0;i < num.length - 2;i++){
if(i > 0 && num[i] == num[i-1])
continue;
int low = i + 1;
int high = num.length - 1;
while(low < high){
int sum = num[i] + num[low] + num[high];
if(sum == target)
return target;
else if(sum > target)
high--;
else
low++;
if(Math.abs(target - sum) < Math.abs(target - res))
res = sum;
}
}
return res;
}
12.4sum
題目:給出一個有n個元素的數組S,S中是否有元素a,b,c和d滿足a+b+c+d=目標值?找出數組S中所有滿足條件的四元組。注意:四元組(a、b、c、d)中的元素必須按非降序排列。(即a≤b≤c≤d);解集中不能包含重複的四元組。 例如:給出的數組 S = {1 0 -1 0 -2 2}, 目標值 = 0.↵↵ 給出的解集應該是:↵ (-1, 0, 0, 1)↵ (-2, -1, 1, 2)↵ (-2, 0, 0, 2)
分析:固定一個數,就可把問題轉換爲滿足目標值得三元組。
public ArrayList<ArrayList<Integer>> fourSum(int[] num, int target) {
ArrayList<ArrayList<Integer>> res = new ArrayList<>();
if(num.length < 4)
return res;
Arrays.sort(num);
for(int i = 0;i < num.length - 3;i++){
if(num[i] + num[i+1] + num[i+2] + num[i+3] > target)
return res;
if(i > 0 && num[i] == num[i-1])
continue;
if(num[i] + num[num.length - 1] + num[num.length - 2] + num[num.length - 3] < target)
continue;
for(int j = i + 1;j < num.length - 2;j++){
if(num[i] + num[j] + num[j+1] + num[j+2] > target)
break;
if(j > i + 1 && num[j] == num[j-1])
continue;
if(num[i] + num[j] + num[num.length - 1] + num[num.length - 2] < target)
continue;
int low = j + 1;
int high = num.length - 1;
while(low < high){
if(num[i] + num[j] + num[low] + num[high] == target){
ArrayList<Integer> list = new ArrayList<>();
list.add(num[i]);list.add(num[j]);list.add(num[low]);list.add(num[high]);
res.add(list);
low++;high--;
while(low < high && num[low] == num[low-1])
low++;
while(low < high && num[high] == num[high+1])
high--;
}
else if(num[i] + num[j] + num[low] + num[high] > target)
high--;
else
low++;
}
}
}
return res;
}