配列内の発生の半分以上
タイトル
配列の半分の長さを超える数が配列にあります。この数を見つけてください。たとえば、長さ{1,2,3,2,2,2,5,4,2}の配列を入力します。数値2は配列に5回出現するため、配列の長さの半分以上なので、出力2になります。存在しない場合は0を出力します。
アイデア
アイデア1
重要な前提:数値が配列の長さの半分を超えて繰り返される場合、配列の中央の数は繰り返される数でなければなりません。
したがって、次のアイデアを持つことができます。
- 高速ソートパーティション関数を使用して、配列の中央値でピボットを継続的に見つけます。
- パーティションによって返されるインデックスが中央の左側にある場合は、[インデックス+ 1、右]から検索を続けます。
- パーティションによって返されるインデックスがmidの右側にある場合は、[left、index-1]から検索を続けます
- インデックス==ミッド、リターン
- 配列内でピボットが半分以上繰り返される場合、出力、
- それ以外の場合、出力はありません。
アイデア2
別のアイデアがあります:
同じ図がアイデアを相殺しています。
現在の数tと現在の回数nを維持します。
- 初期化中、tはarr [0]、n = 1
- arr [i]がtと同じである場合は下降を続け、n + 1でない場合はn-1
- n == 0の場合、tは数値、n + 1
終了:
- 特定の回数が半分を超えた場合、最後に残されるのは間違いなくそれです。
- 最後に与えられた数字は判断されなければなりません。もう一度繰り返して確認します。
達成する
プログラミング時に2つのエラーがあります。
- 左= pIndex + 1;および右= pIndex-1 ;、その時点で1の増減はなかったため、連続ループが発生し、pIndexは変更されませんでした。
- (回数<= mid)が加算または等しくない場合、サイズ9の配列になります。繰り返し数が4の場合、戻り値は存在しません。それを書くための最良の方法は、時間* 2>長さでなければなりません。
//思路1实现
class Solution {
public:
int partition(vector<int>& numbers, int left, int right)
{
if(numbers.empty() || left<0 || right>=numbers.size() || left>right)
return -1;
int pivot = numbers[left];
while(left<right)
{
while(left<right && numbers[right]>=pivot)
--right;
numbers[left] = numbers[right];
while(left<right && numbers[left]<=pivot)
++left;
numbers[right] = numbers[left];
}
numbers[left] = pivot;
return left;
}
int MoreThanHalfNum_Solution(vector<int> numbers) {
int length = numbers.size();
if(length==0) return 0;
int left = 0;
int right = length-1;
int mid = length/2;
int pIndex = partition(numbers, left, right);
while(pIndex!=mid)
{
if(pIndex<mid)
{
left = pIndex+1; //注意这里要加1
pIndex = partition(numbers, left, right);
}
else
{
right = pIndex-1; //注意这里要改变
pIndex = partition(numbers, left, right);
}
}
int targetNum = numbers[pIndex];
int times = 0;
for(auto t : numbers)
{
if(t == targetNum)
++times;
}
if(times<=mid) //注意临界值判断,其实 if(!(2*times>length))更直观
return 0;
return targetNum;
}
};
//思路2实现
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers) {
if(numbers.empty()) return 0;
int target = numbers.front();
int n = 1;
for(int i=1; i<numbers.size(); ++i)
{
if(n==0)
{
target = numbers[i];
++n;
}
else
{
if(target == numbers[i])
++n;
else
--n;
}
}
if(n<=0)
return 0;
int times = 0;
for(auto val:numbers)
{
if(val == target)
++times;
}
if(2*times>numbers.size())
return target;
else
return 0;
}
};