C++完成一維向量扭轉算法。本站提示廣大學習愛好者:(C++完成一維向量扭轉算法)文章只能為提供參考,不一定能成為您想要的結果。以下是C++完成一維向量扭轉算法正文
在《編程珠玑》一書的第二章提到了n元一維向量扭轉算法(又稱數組輪回移位算法)的五種思緒,而且比擬了它們在時光和空間機能上的差別和好壞。本文遷就這一算法做較為深刻的剖析。詳細以下所示:
1、成績描寫
將一個n元一維向量向左扭轉i個地位。例如,假定n=8,i=3,向量abcdefgh扭轉為向量defghabc。簡略的代碼應用一個n元的中央向量在n步內可完成該任務。你可否僅應用幾十個額定字節的內存空間,在反比於n的時光內完成向量的扭轉?
2、處理計劃
思緒一:將向量x中的前i個元素復制到一個暫時數組中,接著將余下的n-i個元素左移i個地位,然後再將前i個元素從暫時數組中復制到x中余下的地位。
機能:這類辦法應用了i個額定的地位,假如i很年夜則發生了過年夜的存儲空間的消費。
C++代碼完成以下:
/*************************************************************************
> File Name: vector_rotate.cpp
> Author: SongLee
************************************************************************/
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s = "abcdefghijklmn";
cout << "The origin is: " << s << endl;
// 左移個數
int i;
cin >> i;
if(i > s.size())
{
i = i%s.size();
}
// 將前i個元素暫時保留
string tmp(s, 0, i);
// 將殘剩的左移i個地位
for(int j=i; j<s.size(); ++j)
{
s[j-i] = s[j];
}
s = s.substr(0, s.size()-i) + tmp;
cout << "The result is: "<< s << endl;
return 0;
}
思緒二:界說一個函數將x向左扭轉一個地位(當時間反比於n),然後挪用該函數i次。
機能:這類辦法固然空間龐雜度為O(1),但發生了過量的運轉時光消費。
C++代碼完成以下:
/*************************************************************************
> File Name: vector_rotate_1.cpp
> Author: SongLee
************************************************************************/
#include<iostream>
#include<string>
using namespace std;
void rotateOnce(string &s)
{
char tmp = s[0];
int i;
for(i=1; i<s.size(); ++i)
{
s[i-1] = s[i];
}
s[i-1] = tmp;
}
int main()
{
string s = "abcdefghijklmn";
cout << "The origin is: " << s << endl;
// 左移個數
int i;
cin >> i;
if(i > s.size())
{
i = i%s.size();
}
// 挪用函數i次
while(i--)
{
rotateOnce(s);
}
cout << "The result is: "<< s << endl;
return 0;
}
思緒三:挪動x[0]莅臨時變量t中,然後挪動x[i]到x[0]中,x[2i]到x[i],順次類推,直到我們又回到x[0]的地位提取元素,此時改成從暫時變量t中提取元素,然後停止該進程(當下標年夜於n時對n取模或許減去n)。假如該進程沒有挪動全體的元素,就從x[1]開端再次停止挪動,總共挪動i和n的最年夜條約數次。
機能:這類辦法異常精致,像書中所說的一樣可謂奇妙的雜技扮演。空間龐雜度為O(1),時光龐雜度為線性時光,知足成績的機能請求,但還不是最好。
C++代碼完成以下:
/*************************************************************************
> File Name: vector_rotate_2.cpp
> Author: SongLee
************************************************************************/
#include<iostream>
#include<string>
using namespace std;
// 歐幾裡德(展轉相除)算法求最年夜條約數
int gcd(int i, int j)
{
while(1)
{
if(i > j)
{
i = i%j;
if(i == 0)
{
return j;
}
}
if(j > i)
{
j = j%i;
if(j == 0)
{
return i;
}
}
}
}
int main()
{
string s = "abcdefghijklmn";
cout << "The origin is: "<< s << endl;
// 左移個數
int i;
cin >> i;
if(i > s.size())
{
i = i%s.size();
}
// 挪動
char tmp;
int times = gcd(s.size(), i);
for(int j=0; j<times; ++j)
{
tmp = s[j];
int pre = j; // 記載上一次的地位
while(1)
{
int t = pre+i;
if(t >= s.size())
t = t-s.size();
if(t == j) // 直到tmp本來的地位j為止
break;
s[pre] = s[t];
pre = t;
}
s[pre] = tmp;
}
cout << "The result is: "<< s << endl;
return 0;
}
思緒四:扭轉向量x現實上就是交流向量ab的兩段,獲得向量ba,這裡a代表x的前i個元素。假定a比b短。將b朋分成bl和br,使br的長度和a的長度一樣。交流a和br,將ablbr轉換成brbla。由於序列a已在它的終究地位了,所以我們可以集中精神交流b的兩個部門了。因為這個新成績和本來的成績是一樣的,所以我們以遞歸的方法停止處理。這類辦法可以獲得優雅的法式,然則須要奇妙的代碼,而且要停止一些思慮能力看出它的效力足夠高。
//完成代碼(略)
思緒五:(最好)將這個成績看作是把數組ab轉換成ba,同時假定我們具有一個函數可以將數組中特定部門的元素逆序。從ab開端,起首對a求逆,獲得arb,然後對b求逆,獲得arbr。最初全體求逆,獲得(arbr)r,也就是ba。
reverse(0, i-1) /*cbadefgh*/ reverse(i, n-1) /*cbahgfed*/ reverse(0, n-1) /*defghabc*/
機能:求逆序的辦法在時光和空間上都很高效,並且代碼異常冗長,很難失足。
C++代碼完成以下:
/*************************************************************************
> File Name: vector_rotate.cpp
> Author: SongLee
************************************************************************/
#include<iostream>
#include<string>
using namespace std;
void reverse(string &s, int begin, int end)
{
while(begin < end)
{
char tmp = s[begin];
s[begin] = s[end];
s[end] = tmp;
++begin;
--end;
}
}
int main()
{
string s = "abcdefghijklmn";
cout << "The origin is: "<< s << endl;
int i;
cin >> i;
if(i > s.size())
{
i = i%s.size();
}
reverse(s, 0, i-1);
reverse(s, i, s.size()-1);
reverse(s, 0, s.size()-1);
cout << "The result is: "<< s << endl;
return 0;
}
3、擴大延長
若何將向量abc扭轉釀成cba?
和後面的成績相似,此向量扭轉對應著非相鄰內存塊的交流模子。解法很類似,即應用恆等式:cba = (arbrcr)r
留意:在面試或口試時,如若湧現向量扭轉(內存塊交流)成績,建議最好應用思緒五答題,不只高效並且簡練。