C語言雙指針多方法旋轉數(shù)組解題LeetCode
LeetCode題目如下:
首先這個中等難度我是沒搞懂,后面才發(fā)現(xiàn)原來中等中在要求多方法上,那就來看看怎么搞定他吧。
暴力思路
首先我說一下我本人的思路,就是函數(shù)進行倒序操作,分三步:
1.整體倒序 :1234567-------7654321
2.前半部分倒序:7654321------- 5674321
3.后半部分倒序:5674321-------5671234
由于題目已經給出了我們 k 的值,我們直接暴力思路(注意是暴力思路非暴力求解),雙指針交換對應的值就行:
void exchange(int* a, int* b) { int n=*a; *a = *b; *b = n; } //交換a,b位置 void reverse(int* nums,int left,int right) { while(left<right) { exchange(&nums[left],&nums[right]); left++; right--; } //對指定范圍內元素進行翻轉操作 } void rotate(int* nums, int numsSize, int k){ k%=numsSize; if(k==0) { return ; //防止k過大或0導致無意義操作 } reverse(nums,0,numsSize-1);//全倒序 reverse(nums,0,k-1);//前半部分倒序 reverse(nums,k,numsSize-1);//后半部分倒序 }
這種方法直觀,最容易想到,特點是思路清晰,完美符合了流程,時間復雜度是O(n),空間復雜度是O(1),將將就就
外加數(shù)組
自力更生不想要咱就尋求外援嘛,直接創(chuàng)建一個額外數(shù)組,前半部分放前面,后半部分放后面不就行了,用 numsSize 表示數(shù)組的長度,我們遍歷原數(shù)組,將原數(shù)組下標為 n 的元素放至新數(shù)組下標為 n+k 的位置,最后將新數(shù)組拷貝至原數(shù)組即可:
void rotate(int* nums, int numsSize, int k){ int arr[numsSize] = {0}; for(int n = 0;n<numsSize;n++) { arr[(k+n)%numsSize] = nums[n]; //nums所有元素向前移動 k 個單位,依次存到數(shù)組arr } for(int n = 0;n<numsSize;n++) { nums[n] = arr[n]; //將arr數(shù)組內容拷貝回原數(shù)組nums }
同理,我們可以選擇直接 malloc 一塊空間出來,這種方法同上不贅述
格局抬高
既然我們能想到 malloc 開辟空間操作,那再想想庫函數(shù)里面好像還有個好東西叫 memcpy ,頭文件:#include <string.h>,memcpy() 用來復制內存,且忽略 \0,其原型為:
void * memcpy ( void * dest, const void * src, size_t num );
memcpy() 會復制 src 所指的內存內容的前 num 個字節(jié)到 dest 所指的內存地址上。memcpy() 并不關心被復制的數(shù)據(jù)類型,只是逐字節(jié)地進行復制,這給函數(shù)的使用帶來了很大的靈活性,可以面向任何數(shù)據(jù)類型進行復制。
代碼如下:
void rotate(int* nums, int numsSize, int k){ int arr[numsSize]; k %= numsSize; memcpy(arr,nums+(numsSize-k),k*(int)sizeof(int)); memcpy(arr+k,nums,(numsSize-k)*(int)sizeof(int)); memcpy(nums,arr,numsSize*(int)sizeof(int)); }
但是在重疊內存塊這方面,memmove() 是比 memcpy() 更安全的方法,所以可能會有一個疑問就是為什么不用 memmove?
memmove 相比 memcpy 更容易造成數(shù)據(jù)丟失。如果目標區(qū)域和源區(qū)域有重疊的話,memmove() 能保證源串在被覆蓋之前將重疊區(qū)域的字節(jié)拷貝到目標區(qū)域中,復制后源區(qū)域的內容會被更改。如果目標區(qū)域與源區(qū)域沒有重疊,則和 memcpy() 函數(shù)功能相同。
強調一下,與 strcpy() 不同的是,memcpy() 會完整的復制 num 個字節(jié),不會因為遇到“\0”而結束。
環(huán)形替代
這是力扣上官方給出的一種方法,需要數(shù)學推導,比較難理解,解析給的是花里胡哨,添油加醋的,我大概概括一下就是把數(shù)組一串元素類比成莫比烏斯環(huán),我們構圖理解就簡單多了(ppt手繪勿噴):
什么意思呢,就是我們就拿k作為遍歷間隔,不斷拿 1+nk(n從0開始) 位置的元素替代 1+ (n+1)k位置元素,直到回到原點,回到原點時因為遍歷間隔>0,必定會有未遍歷的元素我們只需+1 跳到下一位置繼續(xù)上述操作,再使用另一單獨變量,跟蹤當前已經訪問的元素數(shù)量,當該變量 = 元素數(shù)量時遍歷完成,結束遍歷過程。(個人理解,如有不當請聯(lián)系我更正喲~)
int gcd(int a, int b) { return b ? gcd(b, a % b) : a; } void swap(int* a, int* b) { int t = *a; *a = *b, *b = t; } void rotate(int* nums, int numsSize, int k) { k = k % numsSize; int count = gcd(k, numsSize); for (int start = 0; start < count; ++start) { int current = start; int prev = nums[start]; do { int next = (current + k) % numsSize; swap(&nums[next], &prev); current = next; } while (start != current); } }
今天就到這里吧,摸了家人們,更多關于多方法超度旋轉數(shù)組的資料請關注腳本之家其它相關文章!
相關文章
C++實現(xiàn)LeetCode(19.移除鏈表倒數(shù)第N個節(jié)點)
這篇文章主要介紹了C++實現(xiàn)LeetCode(19.移除鏈表倒數(shù)第N個節(jié)點),本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下2021-07-07詳解MFC/C++調用易語言的整數(shù)型和文本型與VS2010互動
在本篇文章里我們給大家分享了MFC/C++調用易語言的整數(shù)型和文本型與VS2010互動相關知識點內容,有興趣的朋友們可以參考下。2018-11-11C++ 數(shù)據(jù)結構 堆排序的實現(xiàn)
這篇文章主要介紹了C++ 數(shù)據(jù)結構 堆排序的實現(xiàn)的相關資料,需要的朋友可以參考下2017-06-06