Likou503。次に大きな要素II ---最初に単調なスタックを出し入れする

503.次の大要素II

ループ配列(最後の要素の次の要素は配列の最初の要素)が与えられた場合、各要素の次に大きい要素を出力します。数値xの次に大きい要素は、配列走査の順序です。この数値の後の最初の数値はそれよりも大きいため、ループ内で次に大きい数値を検索する必要があります。存在しない場合は-1を出力します。

示例 1:

输入: [1,2,1]
输出: [2,-1,2]
解释: 第一个 1 的下一个更大的数是 2;
数字 2 找不到下一个更大的数; 
第二个 1 的下一个最大的数需要循环搜索,结果也是 2。
注意: 输入数组的长度不会超过 10000。

回答:

この質問は別の質問に似ています。毎日の温度暴力の方法は単調なスタックに似ています。興味があれば、見てみることができます。そして、単調なスタックの問題についての私の啓蒙は、内部のビデオから来ています。スタックの問題を理解していない場合は、内部のビデオを見ることができます。

まず、質問の意味を分析する必要があります。探しているのは、ループ配列内の各要素の次に大きい要素であり、存在しない場合は-1を出力しますこの問題の最初の問題は、配列のループにあります
循環配列でない場合は、これが「ファーストインラストアウト」の問題であることがわかりスタック適切に使用して解決します。
つまり、配列シミュレーションスタックを構築し、nums配列をトラバースします。スタックが空の場合は、対応するnums [i]をスタックに直接プッシュします。そうでない場合は、次の判断が行われます
。1。外部の要素スタックはスタックの一番上の要素よりも大きく、この時点で問題は解決されます。これは「次に大きい要素」を意味するため、arr配列使用して、各要素に対応する最大の要素を格納しますスタックの一番上の要素の下の要素をスタックの外側の要素と比較するには、一番上の要素をスタックからポップする必要があります。見つけた大きな要素は、他の要素の大きな要素になる可能性もあるため、次のようにする必要があります。するために使用NUMSアレイ行うこと、それを再び動作「と同様のバックトラック」。
2.スタックの外側の要素は、スタックの一番上の要素よりも大きくありません。つまり、いわゆる「次に大きい要素」が見つからなかったため、スタックの外側の要素をスタックにプッシュできます。

上記の比較の後、質問の意味を満たすarr配列を見つけることができますが、このタイトルは「ループ配列」であることに注意してください
では、最初に、いわゆる「循環」状態をシミュレートする方法について考える必要がありますか?
知っておく必要があるのは、線形トラバーサルの場合はforループ構造がよく使用され循環トラバーサルの場合はwhileループ構造がよく使用されるということです。

したがって、ここでは、nums1をトラバースするときにwhileループを使用します。

そして、ここに重要なポイントがあります。いわゆるリングを形成するために、nums1を2回検索するだけで済みます。
どうして?あなたは見つけることは、いわゆるリングがあるだけという単一の要素が検索されるたびに、それは元の配列の空間的な範囲で検索されます
1、2、4、5、1、1の場合、2を検索し、1より大きいことがわかった場合は検索の過程で4、5、1を検索し、終了する必要があります。しかし、私たちが彼に割り当てた検索スペースnums1配列全体です。2の場合、検索は4、5、1、1です。つまり、2自体を追加すると、nums1配列全体でも検索さます。同じです。 4の場合、検索は5、1、1、2であり、nums1配列全体でもありますしたがって、各要素について、nums1配列空間範囲全体を検索すると、最初の要素1については、nums1をトラバースするだけで十分であり、2については、nums1をトラバースした後、最初の1をトラバースする必要があることがわかりました。 、最初の1と2番目の2をもう一度トラバースする必要があります。最後の1では、トラバースは2つのnums1相当するため、最大値はnums1を2回トラバースすることと同等であるため、nums1を2回直接トラバースする必要があります。完全にトラバースできます。一部の要素では、「より大きな要素」を見つけることできれば、nums1を1回トラバースした後に自然にそれを見つけることできます。、そして、何度も見つけることができなければ役に立たないので、この詳細を通して循環配列の操作を完了することができます。

また、スタックに格納する必要があるのは要素値ではなく、後でarr配列を対応する位置に割り当てる必要があり、要素を見つけやすくなるため、nums配列内の要素添え字である必要があります。下付き文字を格納することにより、numsで。対応する位置、およびマッピングプロセスを完了します

コード:

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* nextGreaterElements(int* nums, int numsSize, int* returnSize){
    
    
   int*arr=(int*)malloc(sizeof(int)*numsSize);//真正返回的数组
   int*temp=(int*)malloc(sizeof(int)*numsSize*2); //注意可能有不会出栈的情况,
   //而我们遍历2次nums1,因此需要两倍的大小
   memset(arr,-1,sizeof(int)*numsSize);//先变成-1
   int top = 0;//栈顶下标
   int i = 0;//此代表你遍历的元素个数
   while(i<2*numsSize-1)//最后一个不找是可以的
   //因为只有最后一个元素会受到“找完”的待遇,而自己本身又不会大于自己
   {
    
    
       int k = 0;
       k=i%numsSize;//取余操作是为了找到真正的环状数组元素对应的下标
       if(top==0)
       {
    
    
           temp[top]=k;
           top++;
           i++;
           continue;
       }
       else
       {
    
    
           if(nums[k]>nums[temp[top-1]])
           {
    
    
               arr[temp[top-1]]=nums[k];//存储进去
               top--;//不出栈比较不了后面的了
               i--;//回溯
           }
           else
           {
    
    
               temp[top]=k;
               top++;
           }
           i++;
           continue;
       }
   }
   *returnSize=numsSize;//表明返回的真正长度
    return arr;
}

おすすめ

転載: blog.csdn.net/xiangguang_fight/article/details/112789742