8.排序數(shù)組常見算法


前幾個題比較簡單,最后一個合并K個有序數(shù)組陶贼,不熟悉STL模板的童鞋可能會抓狂,不要緊扣溺,我已經(jīng)添加了詳細(xì)的注釋骇窍,只要認(rèn)真看下去認(rèn)真思考,相信你可以的锥余!

Remove Duplicates from Sorted Array I,II

對有序數(shù)組去重

每個元素只能出現(xiàn)一次

Remove Duplicates from Sorted Array I

問題描述:給你一個排好序的數(shù)組腹纳,去掉重復(fù)的元素保證每個元素只出現(xiàn)一次。不允許使用另外一個數(shù)組來提供額外的空間驱犹,你必須在原數(shù)組中進(jìn)行這個工作嘲恍。

解題思路:董老師這里運(yùn)用了fast,low兩個值,只有當(dāng)下一個元素與上一個唯一元素不重復(fù)時slow才加1雄驹,slow實(shí)際存儲的去重后新數(shù)組的長度佃牛,而fast是用來遍歷數(shù)組的,當(dāng)fast超過數(shù)組的size時医舆,即意味著遍歷結(jié)束俘侠,我們的去重工作完成象缀。由于原題要求不允許使用額外的空間,所以下面的解法是直接對已重復(fù)的元素所在地址進(jìn)行覆蓋爷速,后面的會被直接移到前面央星。

示例代碼


/*
Given a sorted array, remove the duplicates in place such that each element appear only once and return the new length.
Do not allocate extra space for another array, you must do this in place with constant memory.
For example,
Given input array A = [1,1,2],
Your function should return length = 2, and A is now [1,2].
*/

public class Solution {
    public int removeDuplicates(int[] A) {
        int size = A.length;
        if (size <= 1)
            return size;
        
        int fast = 1;
        int slow = 0;
        while ( fast < size) {
            if (A[slow] != A[fast]) {
                A[slow+1] = A[fast];
                slow++;
            }
            fast++;
        }
        return slow+1;
    }
}

如果我們允許每個元素可以出現(xiàn)至少兩次呢?

Remove Duplicates from Sorted Array II

很簡單惫东,我們加個標(biāo)志位來記錄元素的重復(fù)次數(shù)就好了莉给,當(dāng)重復(fù)次數(shù)超過兩次時我們再進(jìn)行去重處理。

示例代碼:


/*
Follow up for "Remove Duplicates":
What if duplicates are allowed at most twice?
For example,
Given sorted array A = [1,1,1,2,2,3],
Your function should return length = 5, and A is now [1,1,2,2,3].
*/

public class Solution {
    public int removeDuplicates(int[] A) {
        // Start typing your Java solution below
        // DO NOT write main() function
        int size = A.length;
        if (size <= 1)
            return size;
        int fast = 1;
        int slow = 0;
        int dup = 0;
        while ( fast < size) {
            if (A[slow] != A[fast]) {
                A[slow+1] = A[fast];
                slow++;
                dup = 0;
            } else{
                dup++;
                if (dup < 2) {
                    A[slow+1] = A[fast];
                    slow++;
                }
            }
            fast++;
        }
        return slow+1;
    }
}

Intersection of 2 sorted array

在有序數(shù)組中找交集:

array1:[2 3 4 6]  
array2:[3 6 9 10]  

return [3,6]

解題思路:遍歷比較A廉沮、B兩數(shù)組中的元素颓遏,如果出現(xiàn)相等的元素便將該值加入到新的數(shù)組中。無疑滞时,用vector這種動態(tài)容器來充當(dāng)新數(shù)組是最好的叁幢。

示例代碼:


vector<int> findIntersection(vector<int> A, vector<int> B) {
  vector<int> intersection;
  int n1 = A.size();
  int n2 = B.size();
  int i = 0, j = 0;
  while (i < n1 && j < n2) {
      if (A[i] > B[j]) {
          j++;
      } else if (B[j] > A[i]) {
          i++;
      } else {
          intersection.push_back(A[i]);
          i++;
          j++;
      }
  }
  return intersection;
}

Merge Sorted Array

合并有序數(shù)組

1.Merge Two Sorted Array into a new Array
2.Merge Two Sorted Array A and B into A, assume A has enough space.

解題思路:董老師的程序是將組合后的新元素塞到了數(shù)組B里面。大致思路就是我們要想讓B成為合并后的新數(shù)組漂洋,就必須確保B多余的空間大于等于A數(shù)組的長度遥皂,所以下面代碼給A定了n的長度,而B為2*n刽漂。B從第n位開始都初始化為0,意味著后面是可以用來被重新賦值覆蓋的弟孟。在填充新的數(shù)組B的時候贝咙,為了不將前面的元素覆蓋,我們從后往前填充數(shù)組拂募。

示例代碼:


Set A[n] = {2, 11, 54, 87, 99}
Set B[2*n] = = {4, 9, 34, 67, 98, 0, 0, 0, 0, 0}
void Merge(int A[], int B[], int size_b,  int n) {
    indexA=n -1;
    indexB=n -1;
    index_new=2n -1;
    while (index_new >= 0) {
        if (A[indexA] < B[indexB]) {
            B[index_new] = B[indexB];
            indexB--;
            index_new--;
        }
        else {
            B[index_new] = A[indexA];
            indexA--;
            index_new--;
        }

        // Optimization if A or B can be directly copied
        //如果B原有的元素為空庭猩,那么直接像B中填充即可
        if (indexB == -1) {
            while(index_new >= 0)
                B[index_new--] = A[indexA--];
            break;
        }
        //如果A為空,那沒必要合并了
        else if (indexA == -1)
            break;
    }
}

Merge K Sorted List

Merge k sorted linked lists to be one sorted list.

在該題中陈症,董老師用到了優(yōu)先隊(duì)列蔼水,這里我簡單介紹下它的概念。

priority_queue的模板聲明帶有三個參數(shù):
priority_queue<Type, Container, Functional>
其中Type 為數(shù)據(jù)類型录肯, Container 為保存數(shù)據(jù)的容器趴腋,F(xiàn)unctional 為元素比較方式。
Container必須是用數(shù)組實(shí)現(xiàn)的容器论咏,比如 vector, deque 但不能用 list.
STL里面默認(rèn)用的是 vector. 比較方式默認(rèn)用 operator< , 所以如果你把后面?zhèn)z個參數(shù)缺省的話优炬,優(yōu)先隊(duì)列就是大頂堆,隊(duì)頭元素最大谢揪。

優(yōu)先隊(duì)列中元素出隊(duì)列的順序由元素的優(yōu)先級決定绣张,而不是元素進(jìn)入隊(duì)列的次序 必怜,

例如:我們常用的操作就是對數(shù)據(jù)排序,優(yōu)先隊(duì)列默認(rèn)的是數(shù)據(jù)大的優(yōu)先級高葵硕,所以我們無論按照什么順序push一堆數(shù)眉抬,最終在隊(duì)列里總是top出最大的元素。

這里需要重點(diǎn)說明的是當(dāng)你使用priority_queue來push數(shù)據(jù)的時候懈凹,你錄入的數(shù)據(jù)并不會進(jìn)行排序吐辙,只有當(dāng)你pop數(shù)據(jù)的時候,priority_queue才會根據(jù)Functional規(guī)定的數(shù)據(jù)優(yōu)先級來彈出優(yōu)先級最高的那個數(shù)據(jù)蘸劈。

解題思路:利用最小堆這種數(shù)據(jù)結(jié)構(gòu)昏苏,我們首先把k個鏈表的首元素都加入最小堆中,它們會自動排好序威沫。然后我們每次取出最小的那個元素加入我們最終結(jié)果的鏈表中贤惯,然后把剛剛被取出元素的那個鏈表的下一個元素再加入堆中,下次仍從堆中取出最小的元素做相同的操作棒掠,以此類推孵构,直到堆中沒有元素了,此時k個鏈表也合并為了一個鏈表烟很,返回首節(jié)點(diǎn)即可颈墅,注意head(存儲最終結(jié)果的鏈表頭)跟heap(最小堆)不要混淆。

示例代碼如下:


struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};


//重載操作符雾袱,定義優(yōu)先級為數(shù)據(jù)越小優(yōu)先級越大
struct cmp {
    bool operator() (const ListNode *a, const ListNode *b)
    {
        if (a->val < b->val)
            return false;
        else
            return true;
    }
};

ListNode *mergeKLists(vector<ListNode *> &lists) {
    priority_queue<ListNode *, vector<ListNode *>, cmp> heap;

    //將每個鏈表中的頭結(jié)點(diǎn)(即每個數(shù)組開頭最小的值)壓入堆中
    for (int i = 0; i < lists.size(); i++) {
        if (lists[i]) {
            // for the corner case: [{}]
            heap.push(lists[i]);
        }
    }

    ListNode *prevNode = NULL;
    ListNode *head = NULL;
    ListNode *curNode = NULL;

    //不但pop最小堆中的數(shù)據(jù)恤筛,并將那個數(shù)據(jù)填入到新鏈表中
    //直到堆中數(shù)據(jù)為空,停止循環(huán)
    while (!heap.empty()) {
        //curNode始終代表了堆中最小的那個數(shù)據(jù)節(jié)點(diǎn)
        curNode = heap.top();
        heap.pop();

        //第一次循環(huán)芹橡,head指向了堆中最小的數(shù)據(jù)
        if (head == NULL) {
            head = curNode;
        }

        //如果那個最小的數(shù)據(jù)所在的鏈表后面還有數(shù)據(jù)毒坛,那就將他后面的數(shù)據(jù)壓入堆中
        if (curNode->next) {
            heap.push(curNode->next);
        }

        //定義前一個節(jié)點(diǎn)用于新鏈表的迭代更新,
        //第二次prevNode已存在林说,curNode(新的最小數(shù)據(jù))會被接入到prevNode的后面煎殷,鏈表在不斷地被填入新的數(shù)據(jù)
        if (prevNode) {
            prevNode->next = curNode;
        }
        prevNode = curNode;
    }

    //返回我們新鏈表的頭結(jié)點(diǎn),合并K個數(shù)組工作完成
    return head;
}


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末腿箩,一起剝皮案震驚了整個濱河市豪直,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌珠移,老刑警劉巖弓乙,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異剑梳,居然都是意外死亡唆貌,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進(jìn)店門垢乙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來锨咙,“玉大人,你說我怎么就攤上這事追逮±业叮” “怎么了粹舵?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長骂倘。 經(jīng)常有香客問我眼滤,道長,這世上最難降的妖魔是什么历涝? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任诅需,我火速辦了婚禮,結(jié)果婚禮上荧库,老公的妹妹穿的比我還像新娘堰塌。我一直安慰自己,他們只是感情好分衫,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布场刑。 她就那樣靜靜地躺著,像睡著了一般蚪战。 火紅的嫁衣襯著肌膚如雪牵现。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天邀桑,我揣著相機(jī)與錄音瞎疼,去河邊找鬼。 笑死概漱,一個胖子當(dāng)著我的面吹牛丑慎,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播瓤摧,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼玉吁!你這毒婦竟也來了照弥?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤进副,失蹤者是張志新(化名)和其女友劉穎这揣,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體影斑,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡给赞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了矫户。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片片迅。...
    茶點(diǎn)故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖皆辽,靈堂內(nèi)的尸體忽然破棺而出柑蛇,到底是詐尸還是另有隱情芥挣,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布耻台,位于F島的核電站空免,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏盆耽。R本人自食惡果不足惜蹋砚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望摄杂。 院中可真熱鬧坝咐,春花似錦、人聲如沸匙姜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽氮昧。三九已至框杜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間袖肥,已是汗流浹背咪辱。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留椎组,地道東北人油狂。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像寸癌,于是被迫代替她去往敵國和親专筷。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 背景 一年多以前我在知乎上答了有關(guān)LeetCode的問題, 分享了一些自己做題目的經(jīng)驗(yàn)蒸苇。 張土汪:刷leetcod...
    土汪閱讀 12,744評論 0 33
  • LeetCode 刷題隨手記 - 第一部分 前 256 題(非會員)磷蛹,僅算法題,的吐槽 https://leetc...
    蕾娜漢默閱讀 17,778評論 2 36
  • 國家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報批稿:20170802 前言: 排版 ...
    庭說閱讀 10,967評論 6 13
  • 荷爾蒙風(fēng)暴還剩下余波溪烤,開始懂了『我沒那么不舍味咳,你沒那么喜歡我』你我的后來遙遙無期 分手這件事真稱得上是最簡單的最難...
    緋公子閱讀 217評論 0 0
  • 1 很羨慕別人那種說走就走的旅行,沒想到在我的生活中也會發(fā)生檬嘀。 一場馬拉松把我從千里之外的西安勾了過來槽驶。 細(xì)細(xì)想來...