欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++實(shí)現(xiàn)一維向量旋轉(zhuǎn)算法

 更新時(shí)間:2014年08月14日 10:04:27   投稿:shichen2014  
這篇文章主要介紹了C++實(shí)現(xiàn)一維向量旋轉(zhuǎn)算法,非常實(shí)用的經(jīng)典算法,需要的朋友可以參考下

在《編程珠璣》一書的第二章提到了n元一維向量旋轉(zhuǎn)算法(又稱數(shù)組循環(huán)移位算法)的五種思路,并且比較了它們?cè)跁r(shí)間和空間性能上的區(qū)別和優(yōu)劣。本文將就這一算法做較為深入的分析。具體如下所示:

一、問(wèn)題描述

將一個(gè)n元一維向量向左旋轉(zhuǎn)i個(gè)位置。例如,假設(shè)n=8,i=3,向量abcdefgh旋轉(zhuǎn)為向量defghabc。簡(jiǎn)單的代碼使用一個(gè)n元的中間向量在n步內(nèi)可完成該工作。你能否僅使用幾十個(gè)額外字節(jié)的內(nèi)存空間,在正比于n的時(shí)間內(nèi)完成向量的旋轉(zhuǎn)?

二、解決方案

思路一:將向量x中的前i個(gè)元素復(fù)制到一個(gè)臨時(shí)數(shù)組中,接著將余下的n-i個(gè)元素左移i個(gè)位置,然后再將前i個(gè)元素從臨時(shí)數(shù)組中復(fù)制到x中余下的位置。

性能:這種方法使用了i個(gè)額外的位置,如果i很大則產(chǎn)生了過(guò)大的存儲(chǔ)空間的消耗。

C++代碼實(shí)現(xiàn)如下:

/************************************************************************* 
  > 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; 
  // 左移個(gè)數(shù) 
  int i; 
  cin >> i; 
  if(i > s.size()) 
  { 
    i = i%s.size(); 
  } 
  // 將前i個(gè)元素臨時(shí)保存 
  string tmp(s, 0, i); 
  // 將剩余的左移i個(gè)位置 
  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; 
} 

思路二:定義一個(gè)函數(shù)將x向左旋轉(zhuǎn)一個(gè)位置(其時(shí)間正比于n),然后調(diào)用該函數(shù)i次。

性能:這種方法雖然空間復(fù)雜度為O(1),但產(chǎn)生了過(guò)多的運(yùn)行時(shí)間消耗。

C++代碼實(shí)現(xiàn)如下:

/************************************************************************* 
  > 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; 
  // 左移個(gè)數(shù) 
  int i; 
  cin >> i; 
  if(i > s.size()) 
  { 
    i = i%s.size(); 
  } 
  // 調(diào)用函數(shù)i次 
  while(i--) 
  { 
    rotateOnce(s); 
  } 
  cout << "The result is: "<< s << endl; 
  return 0; 
} 


思路三:移動(dòng)x[0]到臨時(shí)變量t中,然后移動(dòng)x[i]到x[0]中,x[2i]到x[i],依次類推,直到我們又回到x[0]的位置提取元素,此時(shí)改為從臨時(shí)變量t中提取元素,然后結(jié)束該過(guò)程(當(dāng)下標(biāo)大于n時(shí)對(duì)n取?;蛘邷p去n)。如果該過(guò)程沒(méi)有移動(dòng)全部的元素,就從x[1]開(kāi)始再次進(jìn)行移動(dòng),總共移動(dòng)i和n的最大公約數(shù)次。

性能:這種方法非常精巧,像書中所說(shuō)的一樣堪稱巧妙的雜技表演。空間復(fù)雜度為O(1),時(shí)間復(fù)雜度為線性時(shí)間,滿足問(wèn)題的性能要求,但還不是最佳。

C++代碼實(shí)現(xiàn)如下:

/************************************************************************* 
  > File Name: vector_rotate_2.cpp 
  > Author: SongLee 
 ************************************************************************/ 
#include<iostream> 
#include<string> 
using namespace std; 
 
// 歐幾里德(輾轉(zhuǎn)相除)算法求最大公約數(shù) 
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; 
  // 左移個(gè)數(shù) 
  int i; 
  cin >> i; 
  if(i > s.size()) 
  { 
    i = i%s.size(); 
  } 
  // 移動(dòng) 
  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原來(lái)的位置j為止 
        break; 
      s[pre] = s[t]; 
      pre = t; 
    } 
    s[pre] = tmp; 
  } 
  cout << "The result is: "<< s << endl; 
  return 0; 
} 

思路四:旋轉(zhuǎn)向量x實(shí)際上就是交換向量ab的兩段,得到向量ba,這里a代表x的前i個(gè)元素。假設(shè)a比b短。將b分割成bl和br,使br的長(zhǎng)度和a的長(zhǎng)度一樣。交換a和br,將ablbr轉(zhuǎn)換成brbla。因?yàn)樾蛄衋已在它的最終位置了,所以我們可以集中精力交換b的兩個(gè)部分了。由于這個(gè)新問(wèn)題和原先的問(wèn)題是一樣的,所以我們以遞歸的方式進(jìn)行解決。這種方法可以得到優(yōu)雅的程序,但是需要巧妙的代碼,并且要進(jìn)行一些思考才能看出它的效率足夠高。

//實(shí)現(xiàn)代碼(略) 

思路五:(最佳)將這個(gè)問(wèn)題看做是把數(shù)組ab轉(zhuǎn)換成ba,同時(shí)假定我們擁有一個(gè)函數(shù)可以將數(shù)組中特定部分的元素逆序。從ab開(kāi)始,首先對(duì)a求逆,得到arb,然后對(duì)b求逆,得到arbr。最后整體求逆,得到(arbr)r,也就是ba。

reverse(0, i-1)  /*cbadefgh*/
reverse(i, n-1) /*cbahgfed*/
reverse(0, n-1) /*defghabc*/

性能:求逆序的方法在時(shí)間和空間上都很高效,而且代碼非常簡(jiǎn)短,很難出錯(cuò)。

C++代碼實(shí)現(xiàn)如下:

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

三、擴(kuò)展延伸

如何將向量abc旋轉(zhuǎn)變成cba?

和前面的問(wèn)題類似,此向量旋轉(zhuǎn)對(duì)應(yīng)著非相鄰內(nèi)存塊的交換模型。解法很相似,即利用恒等式:cba = (arbrcr)r

注意:在面試或筆試時(shí),如若出現(xiàn)向量旋轉(zhuǎn)(內(nèi)存塊交換)問(wèn)題,建議最好使用思路五答題,不僅高效而且簡(jiǎn)潔。

相關(guān)文章

  • C++LeetCode數(shù)據(jù)結(jié)構(gòu)基礎(chǔ)詳解

    C++LeetCode數(shù)據(jù)結(jié)構(gòu)基礎(chǔ)詳解

    這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode數(shù)據(jù)結(jié)構(gòu),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • 淺談關(guān)于C++memory_order的理解

    淺談關(guān)于C++memory_order的理解

    這篇文章主要介紹了淺談關(guān)于C++memory_order的理解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • 詳解C++ 多態(tài)的實(shí)現(xiàn)及原理

    詳解C++ 多態(tài)的實(shí)現(xiàn)及原理

    這篇文章主要介紹了C++ 多態(tài)的實(shí)現(xiàn)及原理,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-05-05
  • C++之OpenCV圖像高光調(diào)整具體流程

    C++之OpenCV圖像高光調(diào)整具體流程

    PS中的高光命令是一種校正由于太接近相機(jī)閃光燈而有些發(fā)白的焦點(diǎn)的方法,對(duì)高光區(qū)和非高光區(qū)的邊緣作平滑處理,接下來(lái)通過(guò)本文給大家分享C++之OpenCV圖像高光調(diào)整具體流程,感興趣的朋友一起看看吧
    2021-09-09
  • 華為機(jī)試題之統(tǒng)計(jì)單詞個(gè)數(shù)實(shí)例代碼

    華為機(jī)試題之統(tǒng)計(jì)單詞個(gè)數(shù)實(shí)例代碼

    這篇文章主要介紹了華為機(jī)試題之統(tǒng)計(jì)單詞個(gè)數(shù)實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • C++基本用法實(shí)踐之模板詳解

    C++基本用法實(shí)踐之模板詳解

    C++的模板是泛型編程思想的一種實(shí)現(xiàn),模板不光支持函數(shù)模板,還有類模板等,本文主要來(lái)和大家聊聊C++中模板的相關(guān)用法,需要的可以參考一下
    2023-07-07
  • C++中用new創(chuàng)建二維數(shù)組和指針數(shù)組實(shí)例代碼

    C++中用new創(chuàng)建二維數(shù)組和指針數(shù)組實(shí)例代碼

    這篇文章主要介紹了C++中用new創(chuàng)建二維數(shù)組和指針數(shù)組實(shí)例代碼,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下
    2017-03-03
  • 算法之排序算法的算法思想和使用場(chǎng)景總結(jié)

    算法之排序算法的算法思想和使用場(chǎng)景總結(jié)

    這篇文章主要介紹了算法之排序算法的算法思想和使用場(chǎng)景總結(jié),本文講解了插入排序、交換排序、選擇排序等幾大類排序算法的特點(diǎn)、思想和使用場(chǎng)景,需要的朋友可以參考下
    2014-08-08
  • C語(yǔ)言版二值圖像統(tǒng)計(jì)連通區(qū)域

    C語(yǔ)言版二值圖像統(tǒng)計(jì)連通區(qū)域

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言版二值圖像統(tǒng)計(jì)連通區(qū)域的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • c++ 編程 幾個(gè)有用的宏詳解

    c++ 編程 幾個(gè)有用的宏詳解

    下面小編就為大家?guī)?lái)一篇c++ 編程 幾個(gè)有用的宏詳解。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-12-12

最新評(píng)論