数据结构与算法

224 阅读2分钟

Basic

Time and Space Complecity

www.bigocheatsheet.com/

Data Strtucture

Array

1. Two Sum

// O(n^2)
class Solution {
    fun twoSum(nums: IntArray, target: Int): IntArray {
        for (i in 0 until nums.size - 1) {
            for (j in i + 1 until nums.size) {
                if (nums[i] + nums[j] == target) {
                    return intArrayOf(i, j)
                }
            }
        }
        return intArrayOf()
    }
}

// O(n)
class Solution {
    fun twoSum(nums: IntArray, target: Int): IntArray {
        val map = HashMap<Int, Int>()
        for ((i, v) in nums.withIndex()) {
            map[v] = i
        }
        for ((i, v) in nums.withIndex()) {
            val anotherValue = target - v
            if (map.containsKey(anotherValue) && map[anotherValue] != i) {
                return intArrayOf(i, map[anotherValue]!!)
            }
        }
        return intArrayOf()
    }
}

4. Median of Two Sorted Arrays

// From left to right, get the min number of the start of nums1 or nums2.
// Step by step, we can get the nTh big number of the two array.
// var totalSize = nums1.size + nums2.size
// var ave = totalSize / 2
// if totalSize is odd, the result is (ave+1)th number;
// else ,there result is ((ave)th number+ (ave+1)th number) / 2
// 
// Time Complexity O((m+n)/2)
// Space complexity O(1)
// 
// Runtime: 300 ms, faster than 100.00% of Kotlin online submissions for Median of Two Sorted Arrays.

class Solution {
    var p1 = -1
    var p2 = -1

    fun findMedianSortedArrays(nums1: IntArray, nums2: IntArray): Double {
        var result = .0
        val totalSize = nums1.size + nums2.size
        var n = 0
        repeat(totalSize / 2) {
            n = getNextNumber(nums1, nums2)
        }
        result = if (totalSize % 2 == 0) {
            (n + getNextNumber(nums1, nums2)) / 2.0
        } else {
            getNextNumber(nums1, nums2).toDouble()
        }
        return result
    }

    private fun getNextNumber(nums1: IntArray, nums2: IntArray): Int {
        var n = 0
        var next1: Int? = null
        var next2: Int? = null
        if (p1 < nums1.size - 1) {
            next1 = nums1[p1 + 1]
        }
        if (p2 < nums2.size - 1) {
            next2 = nums2[p2 + 1]
        }
        if (next1 == null) {
            if (next2 != null) {
                p2++
                n = next2
            }
        } else {
            n = if (next2 == null) {
                p1++
                next1
            } else {
                if (next1 < next2) {
                    p1++
                    next1
                } else {
                    p2++
                    next2
                }
            }
        }
        return n
    }
}

Stack/Queue

PriorityQueue

LinkedList

2. Add Two Numbers

/**
 * Definition for singly-linked list.
 * class ListNode(var `val`: Int = 0) {
 *     var next: ListNode? = null
 * }
 */
class Solution {
    fun addTwoNumbers(l1: ListNode?, l2: ListNode?): ListNode? {
        var p1 = l1
        var p2 = l2
        var carry = 0
        var sum = 0
        val dummyHead: ListNode = ListNode(0)
        var curr: ListNode? = dummyHead
        while (p1 != null || p2 != null || carry != 0) {
            sum = getValueOrZero(p1) + getValueOrZero(p2) + carry
            carry = sum / 10
            curr?.next = ListNode(sum % 10)
            curr = curr?.next
            p1 = p1?.next
            p2 = p2?.next
        }
        return dummyHead.next
    }
    
    private fun getValueOrZero(l: ListNode?): Int {
        return l?.`val` ?: 0
    }
}

3. Longest Substring Without Repeating Characters

import java.util.LinkedList

class Solution {
    fun lengthOfLongestSubstring(s: String): Int {
        var max = 0
        val list = LinkedList<Char>()
        for (c in s.toCharArray()) {
            val indexOfCharInString = list.lastIndexOf(c)
            if (indexOfCharInString != -1) {
                for (i in 0..indexOfCharInString) {
                    list.removeFirst()
                }
            }
            list.add(c)
            if (list.size > max) {
                max = list.size
            }
        }
        return max
    }
}

Queue/Priority queue

Stack

Tree/Binary Search Tree

Hash Table

Disjoint Set

Trie

BoolmFilter

LRU Cache

Algorithm

Greedy

Recursion/Backtrace

Traversal

Breadth-First-Search/Depth-First-Search

Divider and Conquer

Dynamic Programming

5. Longest Palindromic Substring

class Solution {
    var start = 0
    var end = 0
    var max = 0

    fun longestPalindrome(s: String): String {
        if (s.isEmpty()) {
            return s
        }
        val ca = s.toCharArray()
        for (i in 0 until s.length) {
            var j = 0
            var k = 0
            while (i + j + 1 < s.length) {
                // handle situations like "aa..."
                if (ca[i] == ca[i + 1 + j]) {
                    updateMaxIfNeed(2 + j, i, i + j + 1)
                    j++
                } else {
                    break
                }
            }
            // expandAroundCenter
            while (i - k >= 0 && i + j + k < s.length) {
                // dynamic compare start and end char
                if (ca[i - k] == ca[i + j + k]) {
                    updateMaxIfNeed(1 + j + k * 2, i - k, i + k + j)
                } else {
                    break
                }
                k++
            }
        }
        return s.substring(start, end + 1)
    }

    private fun updateMaxIfNeed(subLen: Int, s: Int, e: Int) {
        if (subLen > max) {
            max = subLen
            start = s
            end = e
        }
    }
}

Binary Search

Graph