毎日ACシリーズ(2):最も近い3及び数

1タイトル

leetcode番号16は、目標の数、アレイ内の3つの数字、およびターゲット番号の数には3つの最も近くの特定の配列を与えられました。
ここに画像を挿入説明

2暴力

暴力の伝統的先着順、O(N3):

int temp = nums[0]+nums[1]+nums[2];
for(int i=0;i<nums.length;++i)
    for(int j=i+1;j<nums.length;++j)
        for(int k=j+1;k<nums.length;++k)
        {
            int temp1 = nums[i]+nums[j]+nums[k];
            if(Math.abs(temp-target) > Math.abs(temp1-target))
            {
                temp = temp1;
                if(temp == target)
                    return target;
            }
        }
return temp;

その後。
ここに画像を挿入説明
光栄は、ああ、実際に直接暴力を与えました。

3 O(N2)

継続していない場合はまあ、私自身は、直接暴力の後、3サイクル、深刻なものに従事する、暴力のこの種を立つことができなかったたびに3つの数字を追加し、ターゲットが直接リターンであれば、ターゲットの距離を決定し、しかし、... O(N3)ああ...
実際には、これはそれを使用することもできるで記事にする方法を述べたダブルポインタ、配列、その後、固定数、開始と先端の終わりに、2つのポインタをソートし、その後に進みます中間的なアプローチ。

Arrays.sort(nums);
int t1 = nums[0]+nums[1]+nums[2];
for(int i=0;i<nums.length-2;++i)
{
    int left = i+1;
    int right = nums.length-1;

    while(left < right)
    {
        int t2 = nums[i]+nums[left]+nums[right];
        if(t2 == target)
            return target;
        else if(t2 > target)
            --right;
        else 
            ++left;
        if(abs(t1-target) > abs(t2-target))
        {
            t1 = t2;
        }
    }
}
return t1;

まず、ソート配列、NUMS [I]は、= NUM​​S [I] + NUMS [左] + NUMS [右]ターゲットとの間の関係を分析し、それはより大きい算出T2に応じて、左右二つのポインタ2つに、固定された数であります左に右ポインタが移動し、右に移動し、左ポインタ、2出会うまでポインタよりも小さくなっています。ソートは、(N Nログ)Oを必要とする2サイクルはO(N 2)が必要であり、全体的な時間計算量はO(N 2)です。
ここに画像を挿入説明

4衝撃2msの

最大と最小の剪定とループの内部のためのその最初の答え、2msの、本当に速い、ほとんど手書き高速行のビットを参照します。

4.1手書き速い行

:いくつかのアルゴリズムの組み合わせであるビットは、Arrays.sort()アルゴリズム、検索するには
ここに画像を挿入説明
ソース

配列の長さは、以下47以上286以下である場合にのみ、このように直接に関係なく直接使用高速行番号の長さ、ここで高速放電を手書き、クイックソートと呼ぶことにします。
(原則は...高速の手書き行や難易度を少し、と言うことではありません)

public void qs(int [] nums,int l,int r)
{
    if(l < r-1)
    {
        int t = l;
        int ll = l+1;
        int rr = r-1;
        int temp;
        while(true)
        {
            while(t < rr && nums[t] < nums[rr])
                --rr;
            if(t < rr)
            {
                temp = nums[rr];
                nums[rr] = nums[t];
                nums[t] = temp;
                t = rr--;
            }
            else
                break;
            while(ll < t && nums[ll] < nums[t])
                ++ll;
            if(ll < t)
            {
                temp = nums[ll];
                nums[ll] = nums[t];
                nums[t] = temp;
                t = ll++;
            }
            else
                break;
        }
        qs(nums,l,t);
        qs(nums,t+1,r);
    }
}

もともと2つのループ状態ながら、

while(ll < rr && ...)

その後、レンジ間違ったバグ、調子ビットのうち、見つかった、2の間に変更:

while(t < rr && ...)
while(ll < t && ...)

4.2最大値と最小剪定

プルーニングは固定されている最小数を計算することである、そして、二つの最小目標数の大きさを決定し、この最小値が目標より大きい場合、結果は、しかし、最小値であってもよいことはできません他の値は、最小値、及び目標よりも大きいので、次いでだけ遠くの目標値から、それは最小の中断直後に決定され、他の値に加えます。

二つの数が計算され、目標の最大サイズは、以下の目標値よりも、結果は最大値であってもよい場合は、固定の数は、他の値が後に決定することができなかったと判断されると最大プルーニングは、類似していますまた、直接の休憩。

int left = i+1;
int right = nums.length-1;
if(left < right)
{
    int min = nums[i] + nums[left] + nums[left+1];
    if(min > target)
    {
        if(abs(min - target) < abs(t1 - target))
            t1 = min;
        continue;
    }
}

int max = nums[i] + nums[right] + nums[right-1];
if(max < target)
{
    if(abs(max - target) < abs(t1 - target))
        t1 = max;
    continue;
}

4.3ああ...

ここに画像を挿入説明
単語、楽しいです。

5ソース

githubのの
コード雲

公開された47元の記事 ウォンの賞賛4 ビュー4127

おすすめ

転載: blog.csdn.net/qq_27525611/article/details/104078031