題目:有已經排好序的陣列arr[0:k-1]和arr[k:n-1],現在將兩個陣列合併成乙個大的有序陣列。要求:時間複雜度最壞的情況下為0(n),空間複雜的度為o(1)。
之前看過《演算法筆記》上面將遞迴時,有個two pointers思想,講的正好是怎麼將兩個有序陣列在時間複雜度為o(n)的情況下合併成乙個大的有序陣列。但是這種思想所用到的空間複雜度為o(n),本題中就不適用。
筆者的想法是選擇arr[i:k-1]和arr[j:n-1](初始時i=0,j=k)中最小的數,如果該數在arr[j:n-1]中,那麼該數必定時arr[j],交換arr[i]與arr[j],則(如果)該數在arr[i:k-1]中,直接i++即可。這種想法,由於還要將arr[j:n-1]在進行排序,最壞情況下的時間複雜度相比於o(n)增加到o(nlogn)。筆者想不出了什麼高效的演算法,於是偷偷看解答書。?
《演算法設計與分析習題解答》中提供了一種思想----->迴圈右移陣列方法。書中講的這個方法的大概思想如下:在arr[0:k-1]中找出arr[i](i範圍是0~k-1)在arr[k:n-1]中的位置(二分查詢法),記為pos,在計算pos到k的距離,則從i到pos一直往復迴圈,次數為距離。
**如下可能不好懂,但一定要認真理解。
#include using namespace std;
//演算法實現:用o(1)的空間複雜度,時間複雜度最壞為o(n)的情況下
//合併同乙個陣列的兩個排好序的部分,將其變成乙個大的有序陣列
const int maxn = 1e5+10;
int arr[maxn];
int binarysearch(int x,int left,int right)
if(arr[mid] == x)
return mid;
else
return mid-1;
}void shiftright(int k,int s,int e) //k是移動次數,s是開始迴圈移動的地方,e是結束迴圈移動的地方
}void mer(int k,int n)
}mer(k,n);
for(i=0; icout
}
Leetcode 初級演算法 陣列迴圈右移
給定乙個陣列,將陣列中的元素向右移動 k 個位置,其中 k 是非負數。示例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...
演算法設計與分析筆記 合併排序
合併排序演算法是用分治策略實現對n個元素進行排序的演算法。其基本思想是 將待排序元素分成大小大致相容的2個子集合,分別等於2個子集合進行排序,最終將排好序的子集合合併成為所要求的排好序的集合。非遞迴合併排序演算法 public static void mergesort comparable a,i...
演算法設計與分析
輸入輸出 確定性有窮性 np類問題是非確定性計算模型下的易驗證問題類。所有可以在多項式時間內求解的判定問題構成p類問題 1 二分搜尋技術 二分搜尋演算法的基本思路是對給定已排好序的n個元素a 0 n 1 在這n個元素中找出乙個特定元素x。運用分治的思想,將n個元素以n 2為中心對半分。if x a ...