目次
序文: この章では、leetcode の 3 つの古典的なトピックを紹介します。主なアイデアは次のとおりです。
1: 剣はオファー 58 - II. 左回転文字列 - LeetCode を指します。
2: 977. 順序付けされた配列の二乗 - LeetCode
タイトル説明:
文字列を与え、整数 n を指定すると、文字列の最初の n 文字を文字列の末尾まで回転するように求められます。
この問題の解決策を紹介しましょう: -->
解決策 1:暴力的な解決時間の計算量は o(n^2) です
アイデア: まず 1 文字を左に回転するコードを記述し、それを n 回実行します。
文字を左回転するアイデア: まず最初の要素を tmp 変数で保存し、次に最初の要素の後ろにある要素を前に移動し、その後 tmp を最後の位置に置きます。
写真:
コード:
while(n--)
{
char tmp=*s;
int i =1;
for(i=1;i<strlen(s);i++)
{
s[i-1]=s[i];//挪动元素
}
//最后一个字符改为原来的第一个
s[i-1]=tmp;
}
しかし、時間の複雑さが高すぎるため、ブルート フォース ソリューションは leetcode で実行されました。
したがって、解決策を変更する必要があります。
解決策 2: 3 ステップの逆文字列メソッドの時間計算量は O(N) 空間 O(1)
アイデア: まず文字列の最初の n 文字を反転し、次に n 以降の文字列を反転し、最後に全体の順序を反転します。文字列をその場で変更します。
コードを記述するときは、文字列添字の最大数 n-1 に注意する必要があります。
コード:
void reverse(char** pps,int left,int right)
{
while(left<right)
{
char tmp=(*pps)[left];
(*pps)[left]=(*pps)[right];
(*pps)[right]=tmp;
left++;
right--;
}
}
char* reverseLeftWords(char* s, int n){
reverse(&s,0,n-1);//逆置前n个
reverse(&s,n,strlen(s)-1);//逆置n后面
reverse(&s,0,strlen(s)-1);//整体逆置
return s;
}
解決策 3 : 切断 + 結合 時間 O(n) スペース O(n)
アイデア: 最初の n 文字を取り出し、「\0」文字を追加し、残りの文字を保存し、最後に 2 つの文字を結合し、最後の n 文字を前に置き、最初の n 文字を後ろにつなぎ合わせると、次のことが可能になります。達成するために。
コード:
char* reverseLeftWords(char* s, int n){
n=n%(strlen(s)+1);
char* ret1=(char*)malloc(sizeof(char)*(n+1));//放要旋转的字符还得放'\0'
char* ret2=(char*)malloc(sizeof(char)*(strlen(s)+1));
//先放要旋转的字符串
int i=0;
int j=0;
for(i=0;i<n;i++)
{
ret1[j]=s[i];
j++;
}
ret1[j]='\0';
j=0;
for(i=n;i<strlen(s);i++)
{
ret2[j]=s[i];
j++;
}
int k =0;
while(ret1[k]!='\0')
{
ret2[j++]=ret1[k++];
}
ret2[j]='\0';
return ret2;
}
要約: これら 3 つの方法の中で、2 番目の方法が間違いなく最良ですが、考えるのが最も困難でもあります。
この質問を共有したら、次の質問に進みましょう。
2: 977. 順序付き配列の二乗 - LeetCode メソッド 1:ソートとトラバーサル
アイデア: まず配列内のすべての要素を 2 乗し、それを解決するためにクイック ソートを追加します。時間計算量: O(nlogn) コード実装:
//时间复杂度O(n),空间复杂度O(n),双指针
int* sortedSquares(int* nums, int numsSize, int* returnSize){
int left=0;
int right=numsSize-1;
while(left<=right)
{
if(nums[left]*nums[left]>nums[right]*nums[right])
{
int tmp=nums[right];
nums[right--]=nums[left]*nums[left];
nums[left]=tmp;
}
else
{
nums[right--]=nums[right]*nums[right];
}
}
* returnSize=numsSize;
return nums;
}
写真:
方法 2: 配列は順序配列であることがわかっているため、正方形の値は両側に行くにつれて増加します。そのため、ダブル ポインター法を使用して問題を解決し、大きい要素を最後に配置します。
写真:
コード:
//时间复杂度O(n),空间复杂度O(n),双指针
int* sortedSquares(int* nums, int numsSize, int* returnSize){
//新开辟的一块空间,
int* ret=(int*)malloc(sizeof(int)*numsSize);
int i =numsSize-1;
int left=0;
int right=numsSize-1;
while(left<=right)
{
if(nums[left]<0)
nums[left]=-nums[left];
if(nums[left]>nums[right])
{
ret[i--]=nums[left]*nums[left];
left++;
}
else
{
ret[i--]=nums[right]*nums[right];
right--;
}
}
* returnSize=numsSize;
return ret;
}
この質問は共有されています -_-
3:27 . 要素の削除 - LeetCode
同じ要素を削除する: この質問についてはダブルポインタ法を直接説明しますが、暴力的な解決策については説明しません。
ダブル ポインター メソッド: 2 つのポインターを使用します。1 つのポインターは配列全体の要素を走査するために使用され、もう 1 つのポインターは配列内の要素を変更するために使用されます。
コード:
int removeElement(int* nums, int numsSize, int val){
int fast=0;
int slow=0;
while(fast<numsSize)
{
if(nums[fast]!=val)
{
nums[slow]=nums[fast];
slow++;
}
fast++;
}
return slow;
}
この章の典型的なアルゴリズムの質問は終わりました。役に立ったと思われる場合は、高く評価してください。
何か間違っている点がございましたら、ご指摘お待ちしております。