leetcode算法記錄

數(shù)組中的第K個最大元素

題目

在未排序的數(shù)組中找到第 k 個最大的元素。請注意埂陆,你需要找的是數(shù)組排序后的第 k 個最大的元素吐葱,而不是第 k 個不同的元素。

示例 1:

輸入: [3,2,1,5,6,4] 和 k = 2
輸出: 5
示例 2:

輸入: [3,2,3,1,2,4,5,5,6] 和 k = 4
輸出: 4

解題思路

  1. 利用快排的思想,當(dāng)排序到 k 后囊咏,停止排序,輸出結(jié)果
public static int findKthLargest(int[] nums, int k) {
    fastSort(nums, 0, nums.length - 1);
    return nums[nums.length - k];
}

public static void fastSort(int[] nums, int start, int end) {
    if (nums.length <= 1) {
        return;
    }

    if (start > end) {
        return;
    }

    if (end < 0 || start < 0 || end > nums.length - 1 || start > nums.length - 1) {
        return;
    }

    int left = start, right = end;
    int keyIndex = (left + right) / 2;

    while (left < right) {
        while (right > keyIndex && nums[right] > nums[keyIndex]) {
            right--;
        }

        if (right > keyIndex) {
            swap(nums, keyIndex, right);
            keyIndex = right;
        }

        while (left < keyIndex && nums[left] < nums[keyIndex]) {
            left++;
        }

        if (left < keyIndex) {
            swap(nums, left, keyIndex);
            keyIndex = left;
        }
        left++;
    }

    fastSort(nums, keyIndex + 1, end);
    fastSort(nums, start, keyIndex - 1);

}

三數(shù)之和

頭條重點(diǎn)

題目

給定一個包含 n 個整數(shù)的數(shù)組 nums ,判斷 nums 中是否存在三個元素 a点弯,b,c 矿咕,使得 a + b + c = 0 抢肛?找出所有滿足條件且不重復(fù)的三元組。

注意:答案中不可以包含重復(fù)的三元組碳柱。

例如, 給定數(shù)組 nums = [-1, 0, 1, 2, -1, -4]捡絮,

滿足要求的三元組集合為:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

解題思路

  1. 將數(shù)組排序
  2. 固定一位數(shù),然后通過兩個指針對撞莲镣,尋找總和為 0 的三個數(shù)
public static List<List<Integer>> threeSum(int[] nums) {
    if (nums.length < 3) {
        return Collections.emptyList();
    }

    Set<List<Integer>> res = new HashSet<>();
    Arrays.sort(nums);

    int zCount = 0;
    for (int num : nums) {
        if (num == 0) {
            zCount++;
        }
    }

    for (int i = 0; i < nums.length && nums[i] < 0; i++) {
        int first = nums[I];
        int j = i + 1;
        int k = nums.length - 1;
        while (j < k) {
            int t = nums[j] + nums[k] + first;
            if (t == 0) {
                List<Integer> list = new ArrayList<>();
                list.add(first);
                list.add(nums[j]);
                list.add(nums[k]);

                res.add(list);
                j++;
                k--;
            } else if (t > 0) {
                k--;
            } else {
                j++;
            }
        }

    }

    if (zCount >= 3) {
        List<Integer> list = new ArrayList<>();
        list.add(0);
        list.add(0);
        list.add(0);
        res.add(list);
    }
    return new ArrayList<>(res);
}

環(huán)形鏈表 II

題目

給定一個鏈表福稳,返回鏈表開始入環(huán)的第一個節(jié)點(diǎn)。 如果鏈表無環(huán)剥悟,則返回 null灵寺。

為了表示給定鏈表中的環(huán),我們使用整數(shù) pos 來表示鏈表尾連接到鏈表中的位置(索引從 0 開始)区岗。 如果 pos 是 -1略板,則在該鏈表中沒有環(huán)。

解題思路

  1. 首先通過快慢指針確定鏈表是否有環(huán)
  2. 再使用一個指針從頭節(jié)點(diǎn)與快慢指針相遇節(jié)點(diǎn)同步長前進(jìn)慈缔,最終找到環(huán)的入口
public ListNode detectCycle(ListNode head) {
    ListNode fast = head, slow = head;

    ListNode meetNode = null;
    while (fast != null && fast.next != null) {
        fast = fast.next.next;
        slow = slow.next;

        if (fast == slow) {
            meetNode = fast;
            break;
        }
    }

    if (meetNode == null) {
        return meetNode;
    }

    while (head != meetNode) {
        head = head.next;
        if (head == meetNode) {
            break;
        }

        meetNode = meetNode.next;
    }

    return meetNode;
}

兩數(shù)相加

頭條重點(diǎn)

題目

給出兩個 非空 的鏈表用來表示兩個非負(fù)的整數(shù)叮称。其中,它們各自的位數(shù)是按照 逆序 的方式存儲的藐鹤,并且它們的每個節(jié)點(diǎn)只能存儲 一位 數(shù)字瓤檐。

如果,我們將這兩個數(shù)相加起來娱节,則會返回一個新的鏈表來表示它們的和挠蛉。

您可以假設(shè)除了數(shù)字 0 之外,這兩個數(shù)都不會以 0 開頭肄满。

示例:

輸入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
輸出:7 -> 0 -> 8
原因:342 + 465 = 807

解題思路

public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
    if (l1 == null || l2 == null) {
        return null;
    }

    StringBuilder builder1 = new StringBuilder();
    while (l1 != null) {
        builder1.append(l1.val);
        l1 = l1.next;
    }

    StringBuilder builder2 = new StringBuilder();
    while (l2 != null) {
        builder2.append(l2.val);
        l2 = l2.next;
    }

    BigDecimal bigDecimal1 = new BigDecimal(builder1.reverse().toString());
    BigDecimal bigDecimal2 = new BigDecimal(builder2.reverse().toString());

    String resStr = bigDecimal1.add(bigDecimal2).toPlainString();

    ListNode head = new ListNode(Integer.parseInt(String.valueOf(resStr.charAt(resStr.length() - 1))));
    ListNode cur = head;
    for (int i = resStr.length() - 2; i >= 0; i--) {
        cur.next = new ListNode(Integer.parseInt(String.valueOf(resStr.charAt(i))));
        cur = cur.next;
    }

    return head;
}

反轉(zhuǎn)鏈表

頭條重點(diǎn)

題目

反轉(zhuǎn)一個單鏈表谴古。

示例:

輸入: 1->2->3->4->5->NULL
輸出: 5->4->3->2->1->NULL

解題思路

  1. 三個指針進(jìn)行反轉(zhuǎn)
public ListNode reverseList(ListNode head) {
    if (head == null) {
        return head;
    }

    if (head.next == null) {
        return head;
    }

    ListNode pre = head;
    ListNode cur = head.next;

    while (cur != null) {
        ListNode next = cur.next;
        cur.next = pre;

        pre = cur;
        cur = next;
    }

    head.next = null;

    return pre;
}

合并兩個有序鏈表

題目

將兩個有序鏈表合并為一個新的有序鏈表并返回。新鏈表是通過拼接給定的兩個鏈表的所有節(jié)點(diǎn)組成的稠歉。

示例:

輸入:1->2->4, 1->3->4
輸出:1->1->2->3->4->4

解題思路

public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
    if (l1 == null && l2 == null) {
        return null;
    }

    if (l1 == null) {
        return l2;
    }

    if (l2 == null) {
        return l1;
    }

    ListNode head;

    if (l1.val > l2.val) {
        head = l2;
        l2 = l2.next;
    } else {
        head = l1;
        l1 = l1.next;
    }

    ListNode res = head;
    while (true) {
        ListNode cur;
        if (l1 == null && l2 == null) {
            break;
        }

        if (l1 == null) {
            cur = l2;
            l2 = l2.next;
        } else if (l2 == null) {
            cur = l1;
            l1 = l1.next;
        } else if (l1.val > l2.val) {
            cur = l2;
            l2 = l2.next;
        } else {
            cur = l1;
            l1 = l1.next;
        }

        head.next = cur;
        head = head.next;
    }

    return res;
}

相交鏈表

題目

編寫一個程序掰担,找到兩個單鏈表相交的起始節(jié)點(diǎn)。

解題思路

  1. 首先將兩個鏈表中長的一個向前遍歷怒炸,直到兩個鏈表長度一致
  2. 兩個鏈表同時向前遍歷带饱,便可找到交點(diǎn)
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    if (headA == null || headB == null) {
        return null;
    }

    if (headA == headB) {
        return headA;
    }

    int lenA = 1;
    int lenB = 1;
    ListNode temp = headA;
    while (temp.next != null) {
        temp = temp.next;
        lenA++;
    }

    ListNode tailA = temp;

    temp = headB;
    while (temp.next != null) {
        temp = temp.next;
        lenB++;
    }

    ListNode tailB = temp;
    if (tailB != tailA) {
        return null;
    }

    if (lenA > lenB) {
        for (int i = 0; i < lenA - lenB && headA != null; i++) {
            headA = headA.next;
        }

    } else if (lenA < lenB) {
        for (int i = 0; i < lenB - lenA && headB != null; i++) {
            headB = headB.next;
        }
    }

    while (!headA.equals(headB)) {
        headA = headA.next;
        headB = headB.next;
    }

    return headA;
}

合并K個排序鏈表

頭條重點(diǎn)

題目

合并 k 個排序鏈表,返回合并后的排序鏈表阅羹。請分析和描述算法的復(fù)雜度勺疼。

示例:

輸入:
[
  1->4->5,
  1->3->4,
  2->6
]
輸出: 1->1->2->3->4->4->5->6

解題思路

  1. 通過小根堆,將所有元素放入小根堆
  2. 從小根堆依次取出數(shù)據(jù)
public ListNode mergeKLists(ListNode[] lists) {
    if (lists == null) {
        return null;
    }

    Queue<ListNode> set = new PriorityQueue<>(Comparator.comparingInt(o -> o.val));

    for (ListNode node : lists) {
        while (node != null) {
            set.add(node);
            node = node.next;
        }
    }

    ListNode head = new ListNode(-1);
    ListNode res = head;
    ListNode cur;
    while ((cur = set.poll()) != null) {
        head.next = cur;
        head = head.next;
    }

    head.next = null;
    return res.next;
}

翻轉(zhuǎn)字符串里的單詞

題目

給定一個字符串捏鱼,逐個翻轉(zhuǎn)字符串中的每個單詞恢口。

示例 1:

輸入: "the sky is blue"
輸出: "blue is sky the"

說明:

  • 無空格字符構(gòu)成一個單詞。
  • 輸入字符串可以在前面或者后面包含多余的空格穷躁,但是反轉(zhuǎn)后的字符不能包括耕肩。
  • 如果兩個單詞間有多余的空格,將反轉(zhuǎn)后單詞間的空格減少到只含一個问潭。

解題思路

  1. 按空格拆分字符串為字符串?dāng)?shù)組 t
  2. 逆序遍歷字符串?dāng)?shù)組 t猿诸,并組成新的字符串
public String reverseWords(String s) {
    String trimed = s.trim();

    String[] split = trimed.split(" ");

    StringBuilder builder = new StringBuilder();
    for (int i = split.length - 1; i >= 0; i--) {
        String t = split[I];
        if (t.trim().isEmpty()) {
            continue;
        }

        builder.append(t).append(" ");
    }

    return builder.toString().trim();
}

無重復(fù)字符的最長子串

頭條重點(diǎn)

題目

給定一個字符串,請你找出其中不含有重復(fù)字符的 最長子串 的長度狡忙。

輸入: "abcabcbb"
輸出: 3
解釋: 因?yàn)闊o重復(fù)字符的最長子串是 "abc"梳虽,所以其長度為 3。

解題思路

  1. 用 Map 記錄字符所在位置灾茁,當(dāng)遇到重復(fù)字符時窜觉,移動 start 指針
  2. 替換 Map 中下標(biāo)谷炸,并計(jì)算子串長度
public int lengthOfLongestSubstring(String str) {
    if (str == null || str.length() == 0) return 0;

    HashMap<Character, Integer> temp = new HashMap<>();
    char[] chars = str.toCharArray();

    int res = 0, start = 0;
    for (int i = 0; i < chars.length; i++) {
        if (temp.containsKey(chars[i])) {
            start = Math.max(temp.put(chars[i], i) + 1, start);
        }

        temp.put(chars[i], i);
        res = Math.max(res, i - start + 1);

    }

    return res;
}

排序鏈表

頭條重點(diǎn)

題目

在 O(n log n) 時間復(fù)雜度和常數(shù)級空間復(fù)雜度下,對鏈表進(jìn)行排序禀挫。

示例 1:

輸入: 4->2->1->3
輸出: 1->2->3->4
示例 2:

輸入: -1->5->3->4->0
輸出: -1->0->3->4->5

解題思路

  1. 通過快慢指針將鏈表拆分
  2. 遞歸進(jìn)行拆分旬陡,再通過合并兩個排序鏈表的方式進(jìn)行合并
  3. 類似于歸并排序
public ListNode sortList(ListNode head) {
    if (head == null || head.next == null) {
        return head;
    }

    ListNode slow = head, fast = head;
    while (fast.next != null && fast.next.next != null) {
        fast = fast.next.next;
        slow = slow.next;
    }

    ListNode mid = slow.next;
    slow.next = null;

    ListNode l1 = sortList(head);
    ListNode l2 = sortList(mid);

    return merge(l1, l2);
}

private ListNode merge(ListNode l1, ListNode l2) {
    if (l1 == null) {
        return l2;
    }

    if (l2 == null) {
        return l1;
    }

    ListNode head,res;
    if (l1.val > l2.val) {
        head = l2;
        l2 = l2.next;
    } else {
        head = l1;
        l1 = l1.next;
    }
    res = head;
//        head.next = null;

    while (l1 != null || l2 != null) {
        if (l1 == null) {
            head.next = l2;
            l2 = l2.next;
        } else if (l2 == null) {
            head.next = l1;
            l1 = l1.next;
        } else {
            if (l1.val > l2.val) {
                head.next = l2;
                l2 = l2.next;
            } else {
                head.next = l1;
                l1 = l1.next;
            }
        }
        head = head.next;
    }

    return res;
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市语婴,隨后出現(xiàn)的幾起案子描孟,更是在濱河造成了極大的恐慌,老刑警劉巖砰左,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件匿醒,死亡現(xiàn)場離奇詭異,居然都是意外死亡缠导,警方通過查閱死者的電腦和手機(jī)廉羔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來僻造,“玉大人蜜另,你說我怎么就攤上這事〉找猓” “怎么了举瑰?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蔬螟。 經(jīng)常有香客問我此迅,道長,這世上最難降的妖魔是什么旧巾? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任耸序,我火速辦了婚禮,結(jié)果婚禮上鲁猩,老公的妹妹穿的比我還像新娘坎怪。我一直安慰自己,他們只是感情好廓握,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布搅窿。 她就那樣靜靜地躺著,像睡著了一般隙券。 火紅的嫁衣襯著肌膚如雪男应。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天娱仔,我揣著相機(jī)與錄音沐飘,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛耐朴,可吹牛的內(nèi)容都是我干的借卧。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼筛峭,長吁一口氣:“原來是場噩夢啊……” “哼铐刘!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蜒滩,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎奶稠,沒想到半個月后俯艰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡锌订,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年竹握,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辆飘。...
    茶點(diǎn)故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡啦辐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蜈项,到底是詐尸還是另有隱情芹关,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布紧卒,位于F島的核電站侥衬,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏跑芳。R本人自食惡果不足惜轴总,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望博个。 院中可真熱鬧怀樟,春花似錦、人聲如沸盆佣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽共耍。三九已至投蝉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間征堪,已是汗流浹背瘩缆。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留佃蚜,地道東北人庸娱。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓着绊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親熟尉。 傳聞我的和親對象是個殘疾皇子归露,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評論 2 345

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

  • 久違的晴天,家長會斤儿。 家長大會開好到教室時剧包,離放學(xué)已經(jīng)沒多少時間了。班主任說已經(jīng)安排了三個家長分享經(jīng)驗(yàn)往果。 放學(xué)鈴聲...
    飄雪兒5閱讀 7,494評論 16 22
  • 今天感恩節(jié)哎疆液,感謝一直在我身邊的親朋好友。感恩相遇陕贮!感恩不離不棄堕油。 中午開了第一次的黨會,身份的轉(zhuǎn)變要...
    迷月閃星情閱讀 10,551評論 0 11
  • 可愛進(jìn)取肮之,孤獨(dú)成精掉缺。努力飛翔,天堂翱翔戈擒。戰(zhàn)爭美好眶明,孤獨(dú)進(jìn)取。膽大飛翔筐高,成就輝煌赘来。努力進(jìn)取,遙望凯傲,和諧家園犬辰。可愛游走...
    趙原野閱讀 2,716評論 1 1
  • 在妖界我有個名頭叫胡百曉冰单,無論是何事幌缝,只要找到胡百曉即可有解決的辦法。因?yàn)槭侵缓偞蠹乙杂瀭饔灲形摇皟A城百曉”诫欠,...
    貓九0110閱讀 3,255評論 7 3