mMinStack = new Stack<>();
30 |
31 | private void push(int item) {
32 | mStack.push(item);
33 | if (mMinStack.isEmpty() || item < mMinStack.peek()) {
34 | mMinStack.push(item);
35 | } else {
36 | mMinStack.push(mMinStack.peek());
37 | }
38 | }
39 |
40 | private int pop() {
41 | mMinStack.pop();
42 | return mStack.pop();
43 | }
44 |
45 | private int top() {
46 | return mStack.peek();
47 | }
48 |
49 | private int getMin() {
50 | return mMinStack.peek();
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Java/src/com/daily/algothrim/stack/ValidParenthesis.java:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.stack;
2 |
3 | import java.util.Stack;
4 |
5 | /**
6 | * 有效的括号(LeetCode 20)
7 | * 给定一个只包括 '(',')','{','}','[',']'的字符串,判断字符串是否有效。
8 | * 有效字符串需满足:
9 | *
10 | * 左括号必须用相同类型的右括号闭合。
11 | * 左括号必须以正确的顺序闭合。
12 | * 注意空字符串可被认为是有效字符串。
13 | *
14 | * 使用栈实现,遍历字符串,遇到左括号统统入栈,遇到有括号
15 | * 1. 判断栈是否为空,为空则无效
16 | * 2. 从栈中取出一个元素,与当前右括号做匹配,不符合则无效,符合则继续向下操作
17 | * 3. 字符串遍历结束之后,判断栈是否为空,不为空则无效。
18 | */
19 | public class ValidParenthesis {
20 |
21 | public static void main(String[] args) {
22 | System.out.println(new ValidParenthesis().solution("({[[{(([]))}]]})"));
23 | }
24 |
25 | private boolean solution(String s) {
26 | Stack stack = new Stack<>();
27 | for (char c : s.toCharArray()) {
28 | if ('(' == c || '[' == c || '{' == c) {
29 | stack.push(c);
30 | } else {
31 | if (stack.isEmpty()) return false;
32 | char top = stack.pop();
33 | if ((')' == c && '(' != top) || (']' == c && '[' != top) || ('}' == c && '{' != top)) return false;
34 | }
35 | }
36 |
37 | return stack.isEmpty();
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/images/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/idisfkj/daily_algorithm/f8f42b4e5620a43f9797be737d714a52dcaafedc/images/.DS_Store
--------------------------------------------------------------------------------
/images/rouse.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/idisfkj/daily_algorithm/f8f42b4e5620a43f9797be737d714a52dcaafedc/images/rouse.jpeg
--------------------------------------------------------------------------------
/kotlin/kotlin.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/Main.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim
2 |
3 | class Main {
4 |
5 | companion object {
6 |
7 | @JvmStatic
8 | fun main(args: Array) {
9 | println("main")
10 | }
11 |
12 | }
13 |
14 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/backtracking/01Backpack.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.backtracking
2 |
3 | /**
4 | * 01-背包
5 | */
6 | class `01Backpack` {
7 |
8 | companion object {
9 | @JvmStatic
10 | fun main(args: Array) {
11 | `01Backpack`().apply {
12 | backtracking(0, intArrayOf(2, 2, 4, 6, 3), 5, 9, 0)
13 | println(maxW)
14 | }
15 | }
16 | }
17 |
18 | private var maxW = Int.MIN_VALUE
19 |
20 | /**
21 | * O(2^n)
22 | * w: 可装的背包最大重量
23 | * cw: 当前装的重量
24 | * item: 背包重量数组
25 | * n: 背包个数
26 | * i: 当前背包
27 | */
28 | fun backtracking(i: Int, item: IntArray, n: Int, w: Int, cw: Int) {
29 | if (cw == w || i == n) {
30 | if (cw > maxW) maxW = cw
31 | return
32 | }
33 | backtracking(i + 1, item, n, w, cw) // 不装
34 | if (cw + item[i] <= w) { // 装
35 | backtracking(i + 1, item, n, w, cw + item[i])
36 | }
37 | }
38 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/backtracking/01BackpackUpgrade.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.backtracking
2 |
3 | /**
4 | * 01-背包升级版,增加背包价值,求最大价值。
5 | */
6 | class `01BackpackUpgrade` {
7 |
8 | companion object {
9 | @JvmStatic
10 | fun main(args: Array) {
11 | `01BackpackUpgrade`().apply {
12 | backtracking(0, 5, intArrayOf(2, 2, 4, 6, 3), intArrayOf(3, 4, 8, 9, 6), 9, 0, 0)
13 | println(maxV)
14 | }
15 | }
16 | }
17 |
18 | private var maxV = Int.MIN_VALUE
19 |
20 | /**
21 | * O(2^n)
22 | * w: 可装的背包最大重量
23 | * cw: 当前装的重量
24 | * cv: 当前背包价值
25 | * item: 背包重量数组
26 | * value: 背包价值数组
27 | * n: 背包个数
28 | * i: 当前背包
29 | */
30 | fun backtracking(i: Int, n: Int, item: IntArray, value: IntArray, w: Int, cw: Int, cv: Int) {
31 | if (i == n || cw == w) {
32 | if (maxV < cv) maxV = cv
33 | return
34 | }
35 |
36 | backtracking(i + 1, n, item, value, w, cw, cv) // 不装
37 | if (cw + item[i] <= w) { // 装
38 | backtracking(i + 1, n, item, value, w, cw + item[i], cv + value[i])
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/backtracking/MinDist.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.backtracking
2 |
3 | /**
4 | * 棋盘最小路径
5 | *
6 | * 假设我们有一个 n 乘以 n 的矩阵 matrix[n][n]。矩阵存储的都是正整数。棋子起始位置在左上角,终止位置在右下角。
7 | * 我们将棋子从左上角移动到右下角。每次只能向右或者向下移动一位。从左上角到右下角,会有很多不同的路径可以走。
8 | * 我们把每条路径经过的数字加起来看作路径的长度。那从左上角移动到右下角的最短路径长度是多少呢?
9 | */
10 | class MinDist {
11 |
12 | companion object {
13 | @JvmStatic
14 | fun main(args: Array) {
15 | MinDist().apply {
16 | minDist(0, 0, arrayOf(
17 | intArrayOf(1, 3, 5, 9),
18 | intArrayOf(2, 1, 3, 4),
19 | intArrayOf(5, 2, 6, 7),
20 | intArrayOf(6, 8, 4, 3)
21 | ), 4, 0)
22 | println(mMinDist)
23 | }
24 | }
25 | }
26 |
27 | private var mMinDist = Int.MAX_VALUE
28 |
29 | fun minDist(row: Int, column: Int, matrix: Array, n: Int, dist: Int) {
30 | // (row == n && column == n - 1) 最后一步是从上到下到达终点
31 | // (column == n && row == n - 1) 最后一步是从左到右达到终点
32 | if ((row == n && column == n - 1) || (column == n && row == n - 1)) {
33 | if (dist < mMinDist) mMinDist = dist
34 | return
35 | }
36 |
37 | if (row == n || column == n) return
38 |
39 | minDist(row + 1, column, matrix, n, dist + matrix[row][column])
40 |
41 | minDist(row, column + 1, matrix, n, dist + matrix[row][column])
42 | }
43 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/backtracking/MinEdit.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.backtracking
2 |
3 | /**
4 | * 最少编辑次数
5 | * 求把一个字符串变成另一个字符串,需要的最少编辑次数
6 | * 编辑内容包含:增加、删除、修改
7 | */
8 | class MinEdit {
9 |
10 | companion object {
11 | @JvmStatic
12 | fun main(args: Array) {
13 | MinEdit().apply {
14 | minEdit("mitcmu".toCharArray(), "mtacnu".toCharArray(), 0, 0, 0)
15 | println(mMinEdit)
16 | }
17 | }
18 |
19 | }
20 |
21 | private var mMinEdit = Int.MAX_VALUE
22 |
23 | fun minEdit(a: CharArray, b: CharArray, ap: Int, bp: Int, min: Int) {
24 | if (ap == a.size || bp == b.size) {
25 | var temp = min
26 | if (ap < a.size) temp += a.size - ap
27 | if (bp < b.size) temp += b.size - bp
28 | if (temp < mMinEdit) mMinEdit = temp
29 | return
30 | }
31 |
32 | // 1. 相同 a[ap+1]b[bp+1]
33 | // 2. 不相同
34 | // 2.1 a增/b 删 a[ap][bp+1]
35 | // 2.2 b增/a 删 a[ap+1][bp]
36 | // 2.3 ab修改成相同 a[ap+1][bp+1]
37 | if (a[ap] == b[ap]) { // 相同
38 | minEdit(a, b, ap + 1, bp + 1, min)
39 | } else { // 不相同
40 | minEdit(a, b, ap, bp + 1, min + 1) // a增/b 删 a[ap][bp+1]
41 | minEdit(a, b, ap + 1, bp, min + 1) // b增/a 删 a[ap+1][bp]
42 | minEdit(a, b, ap + 1, bp + 1, min + 1) // ab修改成相同a[ap+1][bp+1]
43 | }
44 | }
45 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/bitmap/BitMap.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.bitmap
2 |
3 | import kotlin.random.Random
4 |
5 | /**
6 | * 位图
7 | */
8 | class BitMap(private val nBits: Int) {
9 | companion object {
10 | @JvmStatic
11 | fun main(args: Array) {
12 | BitMap(100000000).apply {
13 | var i = 0
14 | while (i++ < 100000000) {
15 | val random = Random.nextInt(1000000000)
16 | set(random)
17 | }
18 | testTemp.forEach {
19 | if (!get(it)) {
20 | return@apply
21 | }
22 | }
23 | print("success!")
24 | }
25 | }
26 | }
27 |
28 | private val array = IntArray(nBits / 32 + 1) // 32 int 数据占32位
29 | private val testTemp = ArrayList() // 测试集合
30 |
31 | fun set(k: Int) {
32 | if (k > nBits) return
33 | testTemp.add(k)
34 | val bBite = k / 32
35 | val bBiteIndex = k % 32
36 | array[bBite] = array[bBite].or(1.shl(bBiteIndex))
37 | }
38 |
39 | fun get(k: Int): Boolean {
40 | if (k > nBits) return false
41 | val bBite = k / 32
42 | val bBiteIndex = k % 32
43 | return array[bBite].and(1.shl(bBiteIndex)) != 0
44 | }
45 |
46 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/dp/YangHuiTriangleVer.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.dp
2 |
3 | import kotlin.math.min
4 |
5 | /**
6 | * 杨辉三角变体
7 | *
8 | * 每个位置的数字可以随意填写,经过某个数字只能到达下面一层相邻的两个数字。
9 | * 假设你站在第一层,往下移动,我们把移动到最底层所经过的所有数字之和,定义为路径的长度。请你编程求出从最高层移动到最底层的最短路径长度。
10 | */
11 | class YangHuiTriangleVer {
12 |
13 | companion object {
14 | @JvmStatic
15 | fun main(args: Array) {
16 | println(YangHuiTriangleVer().yangHuiTriangle(arrayOf(
17 | intArrayOf(5),
18 | intArrayOf(7, 8),
19 | intArrayOf(2, 3, 4),
20 | intArrayOf(4, 9, 6, 1),
21 | intArrayOf(2, 7, 9, 4, 5)
22 | ), 5))
23 | }
24 | }
25 |
26 | fun yangHuiTriangle(matrix: Array, n: Int): Int {
27 | val status = Array(n) { IntArray(n) }
28 | status[0][0] = matrix[0][0]
29 |
30 | var i = 1
31 |
32 | while (i < n) {
33 | var k = 0
34 | while (k <= i) {
35 | when (k) {
36 | 0 -> status[i][k] = status[i - 1][k] + matrix[i][k]
37 | i -> status[i][k] = status[i - 1][k - 1] + matrix[i][k]
38 | else -> status[i][k] = min(status[i - 1][k - 1], status[i - 1][k]) + matrix[i][k]
39 | }
40 | k++
41 | }
42 | i++
43 | }
44 |
45 | var min = Int.MAX_VALUE
46 | status[n - 1].forEach {
47 | if (it < min) min = it
48 | }
49 |
50 | return min
51 | }
52 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/AddTwoNumbers.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode
2 |
3 | import com.daily.algothrim.linked.LinkedNode
4 |
5 | /**
6 | * 两数相加(leetcode 2)
7 | *
8 | * 给出两个非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字。
9 | *
10 | * 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
11 | *
12 | * 您可以假设除了数字 0 之外,这两个数都不会以 0开头。
13 | *
14 | * 示例:
15 | *
16 | * 输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
17 | * 输出:7 -> 0 -> 8
18 | * 原因:342 + 465 = 807
19 | */
20 | class AddTwoNumbers {
21 | companion object {
22 | @JvmStatic
23 | fun main(args: Array) {
24 | AddTwoNumbers().solution(LinkedNode(2, LinkedNode(4, LinkedNode(3))),
25 | LinkedNode(5, LinkedNode(6, LinkedNode(4))))?.printAll()
26 | }
27 | }
28 |
29 | /**
30 | * O(m+n)
31 | */
32 | fun solution(l1: LinkedNode?, l2: LinkedNode?): LinkedNode? {
33 | var a = l1
34 | var b = l2
35 |
36 | val result = LinkedNode(-1)
37 | var temp: LinkedNode? = result
38 | var carry = 0
39 |
40 | while (a != null || b != null) {
41 | val add = (a?.value ?: 0) + (b?.value ?: 0) + carry
42 | carry = add / 10
43 | temp?.next = LinkedNode(add % 10)
44 | temp = temp?.next
45 | a = a?.next
46 | b = b?.next
47 |
48 | if (carry > 0) temp?.next = LinkedNode(carry)
49 | }
50 |
51 | return result.next
52 | }
53 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/CanPlaceFlowers.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode
2 |
3 | /**
4 | * 605. 种花问题
5 | *
6 | * 假设你有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花卉不能种植在相邻的地块上,它们会争夺水源,两者都会死去。
7 | * 给定一个花坛(表示为一个数组包含0和1,其中0表示没种植花,1表示种植了花),和一个数 n 。能否在不打破种植规则的情况下种入 n 朵花?能则返回True,不能则返回False。
8 | *
9 | * 示例 1:
10 | *
11 | * 输入: flowerbed = [1,0,0,0,1], n = 1
12 | * 输出: True
13 | * 示例 2:
14 | *
15 | * 输入: flowerbed = [1,0,0,0,1], n = 2
16 | * 输出: False
17 | * */
18 | class CanPlaceFlowers {
19 |
20 | companion object {
21 | @JvmStatic
22 | fun main(args: Array) {
23 | println(CanPlaceFlowers().solution(intArrayOf(0, 1, 1, 0, 0, 1, 1), 1))
24 | }
25 | }
26 |
27 |
28 | /**
29 | * O(n)
30 | */
31 | fun solution(flowerbed: IntArray, n: Int): Boolean {
32 | var i = 0
33 | val size = flowerbed.size
34 | var num = 0
35 | while (i < size) {
36 | if (flowerbed[i] == 0 && (i == size - 1 || flowerbed[i + 1] == 0) && (i == 0 || flowerbed[i - 1] == 0)) {
37 | flowerbed[i] = 1
38 | num++
39 | }
40 | i++
41 | }
42 |
43 | return num >= n
44 | }
45 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/CheckPossibility.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode
2 |
3 | /**
4 | * 665. 非递减数列
5 | *
6 | * 给你一个长度为 n 的整数数组,请你判断在 最多 改变 1 个元素的情况下,该数组能否变成一个非递减数列。
7 | * 我们是这样定义一个非递减数列的: 对于数组中所有的 i (0 <= i <= n-2),总满足 nums[i] <= nums[i + 1]。
8 | */
9 | class CheckPossibility {
10 |
11 | companion object {
12 | @JvmStatic
13 | fun main(args: Array) {
14 | println(CheckPossibility().solution(intArrayOf(4, 2, 3)))
15 | println(CheckPossibility().solution(intArrayOf(4, 2, 1)))
16 | println(CheckPossibility().solution(intArrayOf(4, 2)))
17 | println(CheckPossibility().solution(intArrayOf(2)))
18 | println(CheckPossibility().solution(intArrayOf(3, 4, 2, 3)))
19 | }
20 | }
21 |
22 | // 输入: nums = [4,2,3]
23 | // 输出: true
24 | // 解释: 你可以通过把第一个4变成1来使得它成为一个非递减数列。
25 | fun solution(nums: IntArray): Boolean {
26 | val size = nums.size
27 | var adjustTime = 0
28 | for (i in 0 until size - 1) {
29 | val x = nums[i]
30 | val y = nums[i + 1]
31 | if (x > y) {
32 | adjustTime++
33 | if (adjustTime > 1) return false
34 | if (i > 0 && y < nums[i - 1]) {
35 | nums[i + 1] = x
36 | }
37 | }
38 |
39 | }
40 |
41 | return true
42 | }
43 |
44 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/ContainsDuplicate.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode
2 |
3 | /**
4 | * 217. 存在重复元素
5 | *
6 | * 给定一个整数数组,判断是否存在重复元素。
7 | *
8 | * 如果任意一值在数组中出现至少两次,函数返回 true 。如果数组中每个元素都不相同,则返回 false 。
9 | *
10 | * 示例 1:
11 | *
12 | * 输入: [1,2,3,1]
13 | * 输出: true
14 | * 示例 2:
15 | *
16 | * 输入: [1,2,3,4]
17 | * 输出: false
18 | * 示例 3:
19 | *
20 | * 输入: [1,1,1,3,3,4,3,2,4,2]
21 | * 输出: true
22 | * */
23 | class ContainsDuplicate {
24 |
25 | companion object {
26 | @JvmStatic
27 | fun main(args: Array) {
28 | println(ContainsDuplicate().solution(intArrayOf(1, 2, 3, 1)))
29 | println(ContainsDuplicate().solution(intArrayOf(1, 2, 3, 4)))
30 | println(ContainsDuplicate().solution(intArrayOf(1, 1, 1, 3, 3, 4, 3, 2, 4, 2)))
31 | }
32 | }
33 |
34 | // 时间:O(n)
35 | // 空间:O(n)
36 | fun solution(nums: IntArray): Boolean {
37 | val map = hashMapOf()
38 | nums.forEach {
39 | if (map[it] != null) return true
40 | map[it] = true
41 | }
42 | return false
43 | }
44 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/Decode.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode
2 |
3 | /**
4 | * 1720. 解码异或后的数组
5 | *
6 | * 未知 整数数组 arr 由 n 个非负整数组成。
7 | *
8 | * 经编码后变为长度为 n - 1 的另一个整数数组 encoded ,其中 encoded[i] = arr[i] XOR arr[i + 1] 。例如,arr = [1,0,2,1] 经编码后得到 encoded = [1,2,3] 。
9 | *
10 | * 给你编码后的数组 encoded 和原数组 arr 的第一个元素 first(arr[0])。
11 | *
12 | * 请解码返回原数组 arr 。可以证明答案存在并且是唯一的。
13 | */
14 | class Decode {
15 |
16 | companion object {
17 | @JvmStatic
18 | fun main(args: Array) {
19 | Decode().decode(intArrayOf(1, 2, 3), 1).forEach {
20 | println(it)
21 | }
22 | }
23 | }
24 |
25 | // a ^ a = 0
26 | // a ^ 0 = a
27 | // encoded[i] = result[i] ^ result[i + 1]
28 | // encoded[i] ^ result[i] = result[i] ^ result[i] ^ result[i + 1]
29 | // encoded[i] ^ result[i] = result[i + 1]
30 |
31 | // 时间:O(n)
32 | // 空间:O(1)
33 | fun decode(encoded: IntArray, first: Int): IntArray {
34 | val result = IntArray(encoded.size + 1)
35 | result[0] = first
36 | encoded.forEachIndexed { index, i ->
37 | result[index + 1] = i.xor(result[index])
38 | }
39 | return result
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/FairCandySwap.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode
2 |
3 | /**
4 | * 888. 公平的糖果棒交换
5 | * 爱丽丝和鲍勃有不同大小的糖果棒:A[i] 是爱丽丝拥有的第 i 根糖果棒的大小,B[j] 是鲍勃拥有的第 j 根糖果棒的大小。
6 | *
7 | * 因为他们是朋友,所以他们想交换一根糖果棒,这样交换后,他们都有相同的糖果总量。(一个人拥有的糖果总量是他们拥有的糖果棒大小的总和。)
8 | *
9 | * 返回一个整数数组 ans,其中 ans[0] 是爱丽丝必须交换的糖果棒的大小,ans[1] 是 Bob 必须交换的糖果棒的大小。
10 | *
11 | * 如果有多个答案,你可以返回其中任何一个。保证答案存在。
12 | *
13 | */
14 | class FairCandySwap {
15 |
16 | companion object {
17 | @JvmStatic
18 | fun main(args: Array) {
19 | FairCandySwap().solution(intArrayOf(1, 1), intArrayOf(2, 2)).forEach {
20 | println(it)
21 | }
22 | }
23 |
24 | }
25 |
26 | // 输入:A = [1,1], B = [2,2]
27 | // 输出:[1,2]
28 | // O(m+n)
29 | // O(m)
30 | fun solution(A: IntArray, B: IntArray): IntArray {
31 | val map = HashSet()
32 | var sumA = 0
33 | var sumB = 0
34 | val result = IntArray(2)
35 |
36 | for (a in A) {
37 | sumA += a
38 | map.add(a)
39 | }
40 |
41 | for (b in B) {
42 | sumB += b
43 | }
44 |
45 | val sub = (sumA - sumB) / 2
46 |
47 | for (b in B) {
48 | val a = b + sub
49 | if (map.contains(a)) {
50 | result[0] = a
51 | result[1] = b
52 | break
53 | }
54 | }
55 |
56 | return result
57 | }
58 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/FindMaxAverage.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode
2 |
3 | import kotlin.math.max
4 |
5 | /**
6 | * 643. 子数组最大平均数 I
7 | * 给定 n 个整数,找出平均数最大且长度为 k 的连续子数组,并输出该最大平均数。
8 | *
9 | * 示例:
10 | *
11 | * 输入:[1,12,-5,-6,50,3], k = 4
12 | * 输出:12.75
13 | * 解释:最大平均数 (12-5-6+50)/4 = 51/4 = 12.75
14 | */
15 | class FindMaxAverage {
16 |
17 | companion object {
18 | @JvmStatic
19 | fun main(args: Array) {
20 | println(FindMaxAverage().solution(intArrayOf(1, 12, -5, -6, 50, 3), 4))
21 | }
22 | }
23 |
24 | fun solution(nums: IntArray, k: Int): Double {
25 | var maxTotal = 0
26 | var tempTotal = 0
27 | var i = 0
28 | var j = 0
29 | val size = nums.size
30 |
31 | while (i < size) {
32 | if (i < k) {
33 | maxTotal += nums[i]
34 | tempTotal = maxTotal
35 | } else {
36 | tempTotal = tempTotal - nums[j] + nums[i]
37 | maxTotal = max(tempTotal, maxTotal)
38 | j++
39 | }
40 | i++
41 | }
42 | return maxTotal.toDouble() / k
43 | }
44 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/FindMaximumXOR.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode
2 |
3 | /**
4 | * 421. 数组中两个数的最大异或值
5 | *
6 | * 给你一个整数数组 nums ,返回 nums[i] XOR nums[j] 的最大运算结果,其中 0 ≤ i ≤ j < n 。
7 | *
8 | * 进阶:你可以在 O(n) 的时间解决这个问题吗?
9 | */
10 | class FindMaximumXOR {
11 |
12 | companion object {
13 | @JvmStatic
14 | fun main(args: Array) {
15 | println(FindMaximumXOR().findMaximumXOR(intArrayOf(3, 10, 5, 25, 2, 8)))
16 | println(FindMaximumXOR().findMaximumXOR(intArrayOf(8, 10, 2)))
17 | }
18 | }
19 |
20 | // 输入:nums = [3,10,5,25,2,8]
21 | // 输出:28
22 | // 解释:最大运算结果是 5 XOR 25 = 28.
23 | fun findMaximumXOR(nums: IntArray): Int {
24 | var x = 0
25 | for (k in 30 downTo 0) {
26 | val seen = hashSetOf()
27 | for (num in nums) {
28 | seen.add(num.shr(k))
29 | }
30 |
31 | val xNext = x * 2 + 1
32 | var found = false
33 |
34 | for (num in nums) {
35 | if (seen.contains(xNext.xor(num.shr(k)))) {
36 | found = true
37 | break
38 | }
39 | }
40 |
41 | x = if (found) {
42 | xNext
43 | } else {
44 | xNext - 1
45 | }
46 | }
47 | return x
48 | }
49 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/HasCycle.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode
2 |
3 | import com.daily.algothrim.linked.LinkedNode
4 |
5 | /**
6 | * 环形链表(leetcode 141)
7 | */
8 | class HasCycle {
9 |
10 | companion object {
11 | @JvmStatic
12 | fun main(args: Array) {
13 | val head = LinkedNode(1)
14 | val cycleNode = LinkedNode(2)
15 | println(HasCycle().hasCycle(head.apply {
16 | next = cycleNode.apply {
17 | next = LinkedNode(3).apply {
18 | next = LinkedNode(2).apply {
19 | next = LinkedNode(1).apply {
20 | next = cycleNode
21 | }
22 | }
23 | }
24 | }
25 | }))
26 | }
27 | }
28 |
29 | fun hasCycle(head: LinkedNode?): Boolean {
30 | var fast = head
31 | var slow = head
32 |
33 | while (fast?.next != null) {
34 | fast = fast.next?.next
35 | slow = slow?.next
36 | if (slow == fast) return true
37 | }
38 |
39 | return false
40 | }
41 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/KthLargestValue.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode
2 |
3 | /**
4 | * 1738. 找出第 K 大的异或坐标值
5 | *给你一个二维矩阵 matrix 和一个整数 k ,矩阵大小为 m x n 由非负整数组成。
6 | *
7 | * 矩阵中坐标 (a, b) 的 值 可由对所有满足 0 <= i <= a < m 且 0 <= j <= b < n 的元素 matrix[i][j](下标从 0 开始计数)执行异或运算得到。
8 | *
9 | * 请你找出 matrix 的所有坐标中第 k 大的值(k 的值从 1 开始计数)。
10 | */
11 | class KthLargestValue {
12 |
13 | companion object {
14 | @JvmStatic
15 | fun main(args: Array) {
16 | println(KthLargestValue().kthLargestValue(arrayOf(intArrayOf(5, 2), intArrayOf(1, 6)), 1))
17 | println(KthLargestValue().kthLargestValue(arrayOf(intArrayOf(5, 2), intArrayOf(1, 6)), 2))
18 | println(KthLargestValue().kthLargestValue(arrayOf(intArrayOf(5, 2), intArrayOf(1, 6)), 3))
19 | println(KthLargestValue().kthLargestValue(arrayOf(intArrayOf(5, 2), intArrayOf(1, 6)), 4))
20 | }
21 | }
22 |
23 | /**
24 | * 时间:O(mnlog(mn))
25 | * 空间:O(mn)
26 | */
27 | fun kthLargestValue(matrix: Array, k: Int): Int {
28 | val n = matrix.size
29 | val m = matrix[0].size
30 | val result = mutableListOf()
31 |
32 | val pre = Array(n + 1) {
33 | IntArray(m + 1)
34 | }
35 |
36 | for (i in 1..n) {
37 | for (j in 1..m) {
38 | pre[i][j] = pre[i - 1][j].xor(pre[i][j - 1]).xor(pre[i - 1][j - 1]).xor(matrix[i - 1][j - 1])
39 | result.add(pre[i][j])
40 | }
41 | }
42 |
43 | result.sortWith(Comparator { o1, o2 -> o2 - o1 })
44 |
45 | return result[k - 1]
46 | }
47 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/MaxTurbulenceSize.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode
2 |
3 | /**
4 | * 978. 最长湍流子数组
5 | * 当 A 的子数组 A[i], A[i+1], ..., A[j] 满足下列条件时,我们称其为湍流子数组:
6 | *
7 | * 若 i <= k < j,当 k 为奇数时, A[k] > A[k+1],且当 k 为偶数时,A[k] < A[k+1];
8 | * 或 若 i <= k < j,当 k 为偶数时,A[k] > A[k+1] ,且当 k 为奇数时, A[k] < A[k+1]。
9 | * 也就是说,如果比较符号在子数组中的每个相邻元素对之间翻转,则该子数组是湍流子数组。
10 | * 返回 A 的最大湍流子数组的长度。
11 | */
12 | class MaxTurbulenceSize {
13 |
14 | companion object {
15 | @JvmStatic
16 | fun main(args: Array) {
17 | println(MaxTurbulenceSize().solution(intArrayOf(9, 4, 2, 10, 7, 8, 8, 1, 9)))
18 | println(MaxTurbulenceSize().solution(intArrayOf(4, 8, 12, 16)))
19 | println(MaxTurbulenceSize().solution(intArrayOf(100)))
20 | println(MaxTurbulenceSize().solution(intArrayOf(9, 9)))
21 | }
22 | }
23 |
24 | // 输入:[9,4,2,10,7,8,8,1,9]
25 | // 输出:5
26 | // 解释:(A[1] > A[2] < A[3] > A[4] < A[5])
27 | fun solution(arr: IntArray): Int {
28 | val size = arr.size
29 | if (size == 1) return 1
30 |
31 | var max = 0
32 | var temp = 1
33 | var i = 0
34 | var flag = false
35 |
36 | while (i < size - 1) {
37 | val sub = arr[i] - arr[i + 1]
38 | if (sub > 0 && !flag) {
39 | temp++
40 | } else if (sub < 0 && flag) {
41 | temp++
42 | } else {
43 | max = Math.max(max, temp)
44 | temp = if (sub != 0) 2 else 1
45 | }
46 |
47 | flag = sub > 0
48 | i++
49 | }
50 |
51 | max = Math.max(max, temp)
52 | return max
53 | }
54 |
55 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/MaximumProduct.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode
2 |
3 | import kotlin.math.max
4 |
5 | /**
6 | * 628. 三个数的最大乘积
7 | * 给定一个整型数组,在数组中找出由三个数组成的最大乘积,并输出这个乘积。
8 | */
9 | class MaximumProduct {
10 |
11 | companion object {
12 | @JvmStatic
13 | fun main(args: Array) {
14 | println(MaximumProduct().solution(intArrayOf(1, 2, 3, 4)))
15 | }
16 | }
17 |
18 |
19 | // 三个最大数的乘积或者两个最小负数的与最大正数的乘积
20 | fun solution(nums: IntArray): Int {
21 | var max1 = Int.MIN_VALUE
22 | var max2 = Int.MIN_VALUE
23 | var max3 = Int.MIN_VALUE
24 | var min1 = Int.MAX_VALUE
25 | var min2 = Int.MAX_VALUE
26 |
27 | for (num in nums) {
28 | when {
29 | num > max1 -> {
30 | max3 = max2
31 | max2 = max1
32 | max1 = num
33 | }
34 | num > max2 -> {
35 | max3 = max2
36 | max2 = num
37 | }
38 | num > max3 -> max3 = num
39 | }
40 |
41 | if (num < min1) {
42 | min2 = min1
43 | min1 = num
44 | } else if (num < min2) {
45 | min2 = num
46 | }
47 | }
48 |
49 | return max(max1.times(max2).times(max3), max1.times(min1).times(min2))
50 | }
51 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/MinimumDifference.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode
2 |
3 | import com.daily.algothrim.tree.TreeNode
4 | import kotlin.math.min
5 |
6 | /**
7 | * 二叉树的最小绝对差(leetcode 530)
8 | *
9 | * 给你一棵所有节点为非负值的二叉搜索树,请你计算树中任意两节点的差的绝对值的最小值。
10 | * 示例:
11 | *
12 | * 输入:
13 | *
14 | * 1
15 | * \
16 | * 3
17 | * /
18 | * 2
19 | *
20 | * 输出:
21 | * 1
22 | *
23 | * 解释:
24 | * 最小绝对差为 1,其中 2 和 1 的差的绝对值为 1(或者 2 和 3)。
25 | *
26 | * 提示:
27 | * 树中至少有 2 个节点。
28 | */
29 | class MinimumDifference {
30 |
31 | private var mPre = -1
32 |
33 | companion object {
34 | @JvmStatic
35 | fun main(args: Array) {
36 | println(MinimumDifference().getMinimumDifference(TreeNode(5, left = TreeNode(4), right = TreeNode(7))))
37 | }
38 | }
39 |
40 | /**
41 | * O(n)
42 | */
43 | fun getMinimumDifference(root: TreeNode?): Int {
44 | return dfs(root, Int.MAX_VALUE)
45 | }
46 |
47 | /**
48 | * 中序遍历之后是一个递增的有序队列,直接比较
49 | */
50 | private fun dfs(root: TreeNode?, currentMin: Int): Int {
51 | if (root == null) return currentMin
52 | var sCurrentMin: Int
53 | sCurrentMin = dfs(root.left, currentMin)
54 | if (mPre < 0) {
55 | mPre = root.data
56 | } else {
57 | sCurrentMin = min(sCurrentMin, root.data - mPre)
58 | mPre = root.data
59 | }
60 | sCurrentMin = dfs(root.right, sCurrentMin)
61 | return sCurrentMin
62 | }
63 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/NumEquivDominoPairs.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode
2 |
3 | /**
4 | * 1128. 等价多米诺骨牌对的数量
5 | *
6 | * 给你一个由一些多米诺骨牌组成的列表 dominoes。
7 | *
8 | * 如果其中某一张多米诺骨牌可以通过旋转 0 度或 180 度得到另一张多米诺骨牌,我们就认为这两张牌是等价的。
9 | *
10 | * 形式上,dominoes[i] = [a, b] 和 dominoes[j] = [c, d] 等价的前提是 a==c 且 b==d,或是 a==d 且 b==c。
11 | *
12 | * 在 0 <= i < j < dominoes.length 的前提下,找出满足 dominoes[i] 和 dominoes[j] 等价的骨牌对 (i, j) 的数量。
13 | * */
14 | class NumEquivDominoPairs {
15 |
16 | companion object {
17 | @JvmStatic
18 | fun main(args: Array) {
19 | println(NumEquivDominoPairs().solution(arrayOf(
20 | intArrayOf(1, 2),
21 | intArrayOf(2, 1),
22 | intArrayOf(3, 4),
23 | intArrayOf(5, 6)
24 | )))
25 | }
26 | }
27 |
28 | // dominoes[i].size 最大为两位
29 | // O(n)
30 | fun solution(dominoes: Array): Int {
31 | // 组成两位数的正数
32 | val a = IntArray(100)
33 | var count = 0
34 |
35 | for (item in dominoes) {
36 | if (item[0] > item[1]) {
37 | val temp = item[0]
38 | item[0] = item[1]
39 | item[1] = temp
40 | }
41 |
42 | count += a[item[0] * 10 + item[1]]++
43 | }
44 |
45 | return count
46 | }
47 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/NumIslands.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode
2 |
3 | /**
4 | * 200. 岛屿数量
5 | * 给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。
6 | * 岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
7 | * 此外,你可以假设该网格的四条边均被水包围。
8 | */
9 | class NumIslands {
10 |
11 | companion object {
12 | @JvmStatic
13 | fun main(args: Array) {
14 | println(NumIslands().numIslands(
15 | arrayOf(
16 | charArrayOf('1', '1', '1', '1', '0'),
17 | charArrayOf('1', '1', '0', '1', '0'),
18 | charArrayOf('1', '1', '0', '0', '0'),
19 | charArrayOf('0', '0', '0', '0', '0')
20 | )
21 | ))
22 | }
23 | }
24 |
25 | fun numIslands(grid: Array): Int {
26 | if (grid.isNullOrEmpty() || grid[0].isEmpty()) return 0
27 | var result = 0
28 | val r = grid.size
29 | val c = grid[0].size
30 |
31 | for (ir in 0 until r) {
32 | for (ic in 0 until c) {
33 | if (grid[ir][ic] == '1') {
34 | result++
35 | dfs(r, c, ir, ic, grid)
36 | }
37 | }
38 | }
39 |
40 | return result
41 | }
42 |
43 | private fun dfs(r: Int, c: Int, ir: Int, ic: Int, grid: Array) {
44 | if (ir < 0 || ic < 0 || ir >= r || ic >= c || grid[ir][ic] == '0') return
45 |
46 | grid[ir][ic] = '0'
47 | dfs(r, c, ir - 1, ic, grid)
48 | dfs(r, c, ir + 1, ic, grid)
49 | dfs(r, c, ir, ic - 1, grid)
50 | dfs(r, c, ir, ic + 1, grid)
51 | }
52 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/PivotIndex.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode
2 |
3 | /**
4 | * 724. 寻找数组的中心索引
5 | *
6 | * 给定一个整数类型的数组 nums,请编写一个能够返回数组 “中心索引” 的方法。
7 | *
8 | * 我们是这样定义数组 中心索引 的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和。
9 | *
10 | * 如果数组不存在中心索引,那么我们应该返回 -1。如果数组有多个中心索引,那么我们应该返回最靠近左边的那一个。
11 | * */
12 | class PivotIndex {
13 |
14 | companion object {
15 | @JvmStatic
16 | fun main(args: Array) {
17 | println(PivotIndex().solution(intArrayOf(
18 | 1, 7, 3, 6, 5, 6
19 | )))
20 | println(PivotIndex().solution(intArrayOf(
21 | 1, 2, 3
22 | )))
23 | println(PivotIndex().solution(intArrayOf(
24 | -1, -1, -1, -1, -1, -1
25 | )))
26 | }
27 | }
28 |
29 | // 输入:
30 | // nums = [1, 7, 3, 6, 5, 6]
31 | // 输出:3
32 | // 解释:
33 | // 索引 3 (nums[3] = 6) 的左侧数之和 (1 + 7 + 3 = 11),与右侧数之和 (5 + 6 = 11) 相等。
34 | // 同时, 3 也是第一个符合要求的中心索引。
35 | fun solution(nums: IntArray): Int {
36 | var totalSum = 0
37 | var subSum = 0
38 | for (item in nums) {
39 | totalSum += item
40 | }
41 |
42 | nums.forEachIndexed { index, item ->
43 | if (subSum * 2 + item == totalSum) {
44 | return index
45 | }
46 | subSum += item
47 | }
48 |
49 | return -1
50 | }
51 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/SortArrayByParityII.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode
2 |
3 | /**
4 | * 922. 按奇偶排序数组 II
5 | *
6 | * 给定一个非负整数数组 A, A 中一半整数是奇数,一半整数是偶数。
7 | * 对数组进行排序,以便当 A[i] 为奇数时,i 也是奇数;当 A[i] 为偶数时, i 也是偶数。
8 | *
9 | * 你可以返回任何满足上述条件的数组作为答案。
10 | *
11 | * 示例:
12 | *
13 | * 输入:[4,2,5,7]
14 | * 输出:[4,5,2,7]
15 | * 解释:[4,7,2,5],[2,5,4,7],[2,7,4,5] 也会被接受。
16 | * */
17 | class SortArrayByParityII {
18 |
19 | companion object {
20 |
21 | @JvmStatic
22 | fun main(args: Array) {
23 | SortArrayByParityII().solution(intArrayOf(4, 2, 5, 7)).forEach {
24 | println(it)
25 | }
26 | }
27 | }
28 |
29 | fun solution(A: IntArray): IntArray {
30 | var evenIndex = 0
31 | var oddIndex = 1
32 |
33 | while (evenIndex < A.size) {
34 | // 索引为偶数值为奇数
35 | if (A[evenIndex] % 2 != 0) {
36 | while (oddIndex < A.size) {
37 | // 索引为奇数值为偶数
38 | if (A[oddIndex] % 2 == 0) {
39 | val temp = A[evenIndex]
40 | A[evenIndex] = A[oddIndex]
41 | A[oddIndex] = temp
42 | break
43 | }
44 | oddIndex += 2
45 | }
46 | }
47 | evenIndex += 2
48 | }
49 |
50 | return A
51 | }
52 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/StrangePrinter.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode
2 |
3 | /**
4 | * 664: 奇怪的打印机
5 | *
6 | * 有台奇怪的打印机有以下两个特殊要求:
7 | *
8 | * 打印机每次只能打印由 同一个字符 组成的序列。
9 | * 每次可以在任意起始和结束位置打印新字符,并且会覆盖掉原来已有的字符。
10 | * 给你一个字符串 s ,你的任务是计算这个打印机打印它需要的最少打印次数。
11 | */
12 | class StrangePrinter {
13 |
14 | companion object {
15 | @JvmStatic
16 | fun main(args: Array) {
17 | println(StrangePrinter().strangePrinter("aaaabbb"))
18 | println(StrangePrinter().strangePrinter("aba"))
19 | }
20 | }
21 |
22 | /**
23 | * 时间:O(n3)
24 | * 空间:(n2)
25 | */
26 | fun strangePrinter(s: String): Int {
27 | val n = s.length
28 | val f = Array(n) {
29 | IntArray(n)
30 | }
31 |
32 | var i = n - 1
33 | while (i >= 0) {
34 | f[i][i] = 1
35 | for (j in i + 1 until n) {
36 | if (s[i] == s[j]) {
37 | f[i][j] = f[i][j - 1]
38 | } else {
39 | var min = Int.MAX_VALUE
40 | for (k in i until j) {
41 | min = Math.min(min, f[i][k] + f[k + 1][j])
42 | }
43 | f[i][j] = min
44 | }
45 | }
46 | i--
47 | }
48 | return f[0][n - 1]
49 | }
50 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/SubarraysWithKDistinct.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode
2 |
3 | /**
4 | * 992. K 个不同整数的子数组
5 | * 给定一个正整数数组 A,如果 A 的某个子数组中不同整数的个数恰好为 K,则称 A 的这个连续、不一定独立的子数组为好子数组。
6 | *
7 | * (例如,[1,2,3,1,2] 中有 3 个不同的整数:1,2,以及 3。)
8 | *
9 | * 返回 A 中好子数组的数目。
10 | */
11 | class SubarraysWithKDistinct {
12 |
13 | companion object {
14 | @JvmStatic
15 | fun main(args: Array) {
16 | println(SubarraysWithKDistinct().solution(intArrayOf(1, 2, 1, 2, 3), 2))
17 | }
18 | }
19 |
20 | // 输入:A = [1,2,1,2,3], K = 2
21 | // 输出:7
22 | // 解释:恰好由 2 个不同整数组成的子数组:[1,2], [2,1], [1,2], [2,3], [1,2,1], [2,1,2], [1,2,1,2].
23 | fun solution(A: IntArray, K: Int): Int {
24 | return atMostKDistinct(A, K) - atMostKDistinct(A, K - 1)
25 | }
26 |
27 | private fun atMostKDistinct(A: IntArray, K: Int): Int {
28 | val size = A.size
29 |
30 | var left = 0
31 | var right = 0
32 |
33 | var count = 0
34 | var result = 0
35 |
36 | val freg = IntArray(size + 1)
37 |
38 | while (right < size) {
39 | if (freg[A[right]] == 0) {
40 | count++
41 | }
42 | freg[A[right]]++
43 | right++
44 |
45 | while (count > K) {
46 | freg[A[left]]--
47 | if (freg[A[left]] == 0) {
48 | count--
49 | }
50 | left++
51 | }
52 | result += right - left
53 | }
54 | return result
55 | }
56 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/TowSum.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode
2 |
3 | /**
4 | * 两数之和(leetcode 1)
5 | * 给定一个整数数组 nums和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。
6 | *
7 | * 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
8 | *
9 | * 示例:
10 | *
11 | * 给定 nums = [2, 7, 11, 15], target = 9
12 | *
13 | * 因为 nums[0] + nums[1] = 2 + 7 = 9
14 | * 所以返回 [0, 1]
15 | */
16 | class TowSum {
17 |
18 | companion object {
19 | @JvmStatic
20 | fun main(args: Array) {
21 | TowSum().solution(intArrayOf(2, 7, 11, 15), 9).forEach {
22 | println(it)
23 | }
24 | }
25 | }
26 |
27 | /**
28 | * O(n)
29 | */
30 | fun solution(num: IntArray, target: Int): IntArray {
31 | val result = IntArray(2)
32 | val map = hashMapOf()
33 |
34 | num.forEachIndexed { index, i ->
35 | if (map.containsKey(i)) {
36 | map[i]?.let {
37 | return intArrayOf(it, index)
38 | }
39 | }
40 | map[target - i] = index
41 | }
42 | return result
43 | }
44 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/Trap.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode
2 |
3 | /**
4 | * 42. 接雨水
5 | *
6 | * 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
7 | * */
8 | class Trap {
9 |
10 | companion object {
11 | @JvmStatic
12 | fun main(args: Array) {
13 | println(Trap().trap(intArrayOf(0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1)))
14 | }
15 | }
16 |
17 | fun trap(height: IntArray): Int {
18 | if (height.size <= 2) return 0
19 |
20 | val n = height.size
21 | val leftMax = IntArray(n)
22 | val rightMax = IntArray(n)
23 |
24 | leftMax[0] = height[0]
25 | for (i in 1 until n) {
26 | leftMax[i] = Math.max(leftMax[i - 1], height[i])
27 | }
28 |
29 | rightMax[n - 1] = height[n - 1]
30 | var m = n - 2
31 | while (m >= 0) {
32 | rightMax[m] = Math.max(rightMax[m + 1], height[m])
33 | m--
34 | }
35 |
36 | var sum = 0
37 | for (j in 0 until n) {
38 | sum += Math.min(leftMax[j], rightMax[j]) - height[j]
39 | }
40 |
41 | return sum
42 | }
43 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/XorOperation.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode
2 |
3 | /**
4 | * 1486. 数组异或操作
5 | *
6 | * 给你两个整数,n 和 start 。
7 | *
8 | * 数组 nums 定义为:nums[i] = start + 2*i(下标从 0 开始)且 n == nums.length 。
9 | *
10 | * 请返回 nums 中所有元素按位异或(XOR)后得到的结果。
11 | */
12 | class XorOperation {
13 |
14 | companion object {
15 | @JvmStatic
16 | fun main(args: Array) {
17 | println(XorOperation().xorOperation(5, 0))
18 | println(XorOperation().xorOperation(4, 3))
19 | println(XorOperation().xorOperation2(5, 0))
20 | println(XorOperation().xorOperation2(4, 3))
21 | }
22 | }
23 |
24 | fun xorOperation(n: Int, start: Int): Int {
25 | var result = start
26 | for (i in 1 until n) {
27 | result = result.xor(start + 2 * i)
28 | }
29 | return result
30 | }
31 |
32 | fun xorOperation2(n: Int, start: Int): Int {
33 | val s = start.shr(1)
34 | val e = n.and(start).and(1)
35 | val result = sumXor(s - 1).xor(sumXor(s + n - 1))
36 | return result.shl(1).or(e)
37 | }
38 |
39 | private fun sumXor(x: Int): Int {
40 | return when (x % 4) {
41 | 0 -> x
42 | 1 -> 1
43 | 2 -> x + 1
44 | else -> 0
45 | }
46 | }
47 |
48 |
49 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/XorQueries.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode
2 |
3 | /**
4 | * 1310. 子数组异或查询
5 | *
6 | * 有一个正整数数组 arr,现给你一个对应的查询数组 queries,其中 queries[i] = [Li, Ri]。
7 | *
8 | * 对于每个查询 i,请你计算从 Li 到 Ri 的 XOR 值(即 arr[Li] xor arr[Li+1] xor ... xor arr[Ri])作为本次查询的结果。
9 | *
10 | * 并返回一个包含给定查询 queries 所有结果的数组。
11 | */
12 | class XorQueries {
13 |
14 | companion object {
15 | @JvmStatic
16 | fun main(args: Array) {
17 | XorQueries().xorQueries(intArrayOf(1,3,4,8), arrayOf(intArrayOf(0, 1), intArrayOf(1, 2), intArrayOf(0, 3), intArrayOf(3, 3))).apply {
18 | forEach {
19 | println(it)
20 | }
21 | }
22 | }
23 | }
24 |
25 | //输入:arr = [1,3,4,8], queries = [[0,1],[1,2],[0,3],[3,3]]
26 | //输出:[2,7,14,8]
27 | //解释:
28 | //数组中元素的二进制表示形式是:
29 | //1 = 0001
30 | //3 = 0011
31 | //4 = 0100
32 | //8 = 1000
33 | //查询的 XOR 值为:
34 | //[0,1] = 1 xor 3 = 2
35 | //[1,2] = 3 xor 4 = 7
36 | //[0,3] = 1 xor 3 xor 4 xor 8 = 14
37 | //[3,3] = 8
38 | fun xorQueries(arr: IntArray, queries: Array): IntArray {
39 | val querySize = queries.size
40 | val arrSize = arr.size
41 | val result = IntArray(querySize)
42 |
43 | val xorIteration = IntArray(arrSize + 1)
44 | for (i in 0 until arrSize) {
45 | xorIteration[i + 1] = xorIteration[i].xor(arr[i])
46 | }
47 |
48 | for (i in 0 until querySize) {
49 | result[i] = xorIteration[queries[i][0]].xor(xorIteration[queries[i][1] + 1])
50 | }
51 |
52 | return result
53 | }
54 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/AddBinary.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | /**
4 | * 67. 二进制求和
5 | * 给你两个二进制字符串 a 和 b ,以二进制字符串的形式返回它们的和。
6 | *
7 | * 示例 1:
8 | * 输入:a = "11", b = "1"
9 | * 输出:"100"
10 | *
11 | * 示例 2:
12 | * 输入:a = "1010", b = "1011"
13 | * 输出:"10101"
14 | */
15 | class AddBinary {
16 |
17 | companion object {
18 |
19 | @JvmStatic
20 | fun main(args: Array) {
21 | println(AddBinary().addBinary("11", "1"))
22 | println(AddBinary().addBinary("1010", "1011"))
23 | }
24 |
25 | }
26 |
27 | fun addBinary(a: String, b: String): String {
28 | var carry = 0
29 | val result = StringBuilder()
30 |
31 | val n = Math.max(a.length, b.length)
32 | for (i in 0 until n) {
33 | if (i < a.length) {
34 | carry += a[a.length - i - 1] - '0'
35 | }
36 | if (i < b.length) {
37 | carry += b[b.length - i - 1] - '0'
38 | }
39 | result.append(carry % 2)
40 | carry /= 2
41 | }
42 |
43 | if (carry > 0) {
44 | result.append(carry)
45 | }
46 |
47 | result.reverse()
48 |
49 | return result.toString()
50 | }
51 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/AreAlmostEqual.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | /**
4 | * 1790. 仅执行一次字符串交换能否使两个字符串相等
5 | * 给你长度相等的两个字符串 s1 和 s2 。一次 字符串交换 操作的步骤如下:选出某个字符串中的两个下标(不必不同),并交换这两个下标所对应的字符。
6 | * 如果对 其中一个字符串 执行 最多一次字符串交换 就可以使两个字符串相等,返回 true ;否则,返回 false 。
7 | *
8 | * 示例 1:
9 | * 输入:s1 = "bank", s2 = "kanb"
10 | * 输出:true
11 | * 解释:例如,交换 s2 中的第一个和最后一个字符可以得到 "bank"
12 | *
13 | * 示例 2:
14 | * 输入:s1 = "attack", s2 = "defend"
15 | * 输出:false
16 | * 解释:一次字符串交换无法使两个字符串相等
17 | *
18 | * 示例 3:
19 | * 输入:s1 = "kelb", s2 = "kelb"
20 | * 输出:true
21 | * 解释:两个字符串已经相等,所以不需要进行字符串交换
22 | *
23 | * 示例 4:
24 | * 输入:s1 = "abcd", s2 = "dcba"
25 | * 输出:false
26 | */
27 | class AreAlmostEqual {
28 |
29 | companion object {
30 | @JvmStatic
31 | fun main(args: Array) {
32 | println(AreAlmostEqual().areAlmostEqual("bank", "kanb"))
33 | println(AreAlmostEqual().areAlmostEqual("attack", "defend"))
34 | println(AreAlmostEqual().areAlmostEqual("kelb", "kelb"))
35 | println(AreAlmostEqual().areAlmostEqual("abcd", "dcba"))
36 | }
37 | }
38 |
39 | fun areAlmostEqual(s1: String, s2: String): Boolean {
40 | val diff = arrayListOf()
41 |
42 | for (i in s1.indices) {
43 | if (s1[i] != s2[i]) {
44 | if (diff.size >= 2) {
45 | return false
46 | }
47 | diff.add(i)
48 | }
49 | }
50 | if (diff.isEmpty()) return true
51 | if (diff.size != 2) return false
52 |
53 | return s1[diff[0]] == s2[diff[1]] && s1[diff[1]] == s2[diff[0]]
54 | }
55 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/ClimbStairs.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | /**
4 | * 70. 爬楼梯
5 | *
6 | * 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
7 | * 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
8 | * 注意:给定 n 是一个正整数。
9 | */
10 | class ClimbStairs {
11 |
12 | companion object {
13 | @JvmStatic
14 | fun main(args: Array) {
15 | println(ClimbStairs().climbStairs(2))
16 | println(ClimbStairs().climbStairs(3))
17 | println(ClimbStairs().climbStairs2(2))
18 | println(ClimbStairs().climbStairs2(3))
19 | }
20 | }
21 |
22 | fun climbStairs(n: Int): Int {
23 | if (n == 1) return 1
24 | if (n == 2) return 2
25 |
26 | val dp = IntArray(n)
27 | dp[0] = 1
28 | dp[1] = 2
29 |
30 | for (i in 2 until n) {
31 | dp[i] = dp[i - 1] + dp[i - 2]
32 | }
33 |
34 | return dp[n - 1]
35 | }
36 |
37 | fun climbStairs2(n: Int): Int {
38 | var p = 0
39 | var q: Int
40 | var r = 1
41 |
42 | for (i in 0 until n) {
43 | q = p
44 | p = r
45 | r = p + q
46 | }
47 | return r
48 | }
49 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/ContainsNearbyDuplicate.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | /**
4 | * 219. 存在重复元素 II
5 | */
6 | class ContainsNearbyDuplicate {
7 |
8 | companion object {
9 | @JvmStatic
10 | fun main(array: Array) {
11 | println(ContainsNearbyDuplicate().containsNearbyDuplicate(intArrayOf(1, 2, 3, 1), 3))
12 | println(ContainsNearbyDuplicate().containsNearbyDuplicate(intArrayOf(1, 2, 3, 1, 2, 3), 2))
13 | }
14 | }
15 |
16 | fun containsNearbyDuplicate(nums: IntArray, k: Int): Boolean {
17 | val set = hashSetOf()
18 | for (i in nums.indices) {
19 | if (i > k) {
20 | set.remove(nums[i - k - 1])
21 | }
22 | if (!set.add(nums[i])) {
23 | return true
24 | }
25 | }
26 | return false
27 | }
28 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/Generate.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | /**
4 | * 118. 杨辉三角
5 | */
6 | class Generate {
7 |
8 | companion object {
9 | @JvmStatic
10 | fun main(args: Array) {
11 | Generate().generate(5).forEach {list ->
12 | list.forEach {
13 | print(it)
14 | }
15 | print(",")
16 | }
17 | println()
18 | Generate().generate(1).forEach {list ->
19 | list.forEach {
20 | print(it)
21 | }
22 | print(",")
23 | }
24 | }
25 | }
26 |
27 | fun generate(numRows: Int): List> {
28 | val result = arrayListOf>()
29 | for (i in 0 until numRows) {
30 | val row = arrayListOf()
31 | for (j in 0..i) {
32 | if (j == 0 || j == i) {
33 | row.add(1)
34 | } else {
35 | row.add(result[i - 1][j - 1] + result[i - 1][j])
36 | }
37 | }
38 | result.add(row)
39 | }
40 | return result
41 | }
42 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/GetRow.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | /**
4 | * 119. 杨辉三角 II
5 | */
6 | class GetRow {
7 |
8 | companion object {
9 | @JvmStatic
10 | fun main(args: Array) {
11 | GetRow().getRow(3).forEach {
12 | print(it)
13 | }
14 | println()
15 | GetRow().getRow(0).forEach {
16 | print(it)
17 | }
18 | println()
19 | }
20 | }
21 |
22 | fun getRow(rowIndex: Int): List {
23 | var pre = ArrayList()
24 | for (i in 0 .. rowIndex) {
25 | val cur = ArrayList()
26 | for (j in 0..i) {
27 | if (j == 0 || j == i) {
28 | cur.add(1)
29 | } else {
30 | cur.add(pre[j - 1] + pre[j])
31 | }
32 | }
33 | pre = cur
34 | }
35 | return pre
36 | }
37 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/HammingWeight.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | /**
4 | * 191. 位1的个数
5 | */
6 | class HammingWeight {
7 |
8 | companion object {
9 | @JvmStatic
10 | fun main(args: Array) {
11 | println(HammingWeight().hammingWeight(11))
12 | println(HammingWeight().hammingWeight(256))
13 | }
14 | }
15 |
16 | fun hammingWeight(n:Int):Int {
17 | var count = 0
18 | var temp = n
19 | while (temp != 0) {
20 | temp = temp.and(temp - 1)
21 | count++
22 | }
23 | return count
24 | }
25 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/InorderTraversal.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | /**
4 | * 94. 二叉树的中序遍历
5 | */
6 | class InorderTraversal {
7 |
8 | companion object {
9 | @JvmStatic
10 | fun main(args: Array) {
11 | InorderTraversal().inorderTraversal(TreeNode(1).apply {
12 | right = TreeNode(2).apply {
13 | left = TreeNode(3)
14 | }
15 | }).forEach {
16 | print(it)
17 | }
18 | println()
19 | InorderTraversal().inorderTraversal(TreeNode(1)).forEach {
20 | print(it)
21 | }
22 | }
23 | }
24 |
25 | fun inorderTraversal(root: TreeNode?): List {
26 | val list = mutableListOf()
27 | inorder(root, list)
28 | return list
29 | }
30 |
31 | private fun inorder(root: TreeNode?, list: MutableList) {
32 | if (root == null) return
33 | inorder(root.left, list)
34 | list.add(root.`val`)
35 | inorder(root.right, list)
36 | }
37 | }
38 |
39 | class TreeNode(var `val`: Int) {
40 | var left: TreeNode? = null
41 | var right: TreeNode? = null
42 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/InvertTree.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | import java.util.LinkedList
4 |
5 | /**
6 | * 226. 翻转二叉树
7 | */
8 | class InvertTree {
9 |
10 | companion object {
11 | @JvmStatic
12 | fun main(args: Array) {
13 | printlnTree(InvertTree().invertTree(
14 | TreeNode(4).apply {
15 | left = TreeNode(2).apply {
16 | left = TreeNode(1)
17 | right = TreeNode(3)
18 | }
19 | right = TreeNode(7).apply {
20 | left = TreeNode(6)
21 | right = TreeNode(9)
22 | }
23 | }
24 | ))
25 | }
26 |
27 | private fun printlnTree(root: TreeNode?) {
28 | if (root == null) return
29 | val queue = LinkedList()
30 | queue.offer(root)
31 | while (queue.isNotEmpty()) {
32 | val node = queue.poll()
33 | println(node.`val`)
34 | if (node.left != null) {
35 | queue.offer(node.left)
36 | }
37 | if (node.right != null) {
38 | queue.offer(node.right)
39 | }
40 | }
41 | }
42 |
43 | }
44 |
45 | fun invertTree(root: TreeNode?): TreeNode? {
46 | if (root == null) return null
47 |
48 | val left = invertTree(root.left)
49 | val right = invertTree(root.right)
50 | root.left = right
51 | root.right = left
52 | return root
53 | }
54 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/IsHappy.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | /**
4 | * 202. 快乐数
5 | */
6 | class IsHappy {
7 |
8 | companion object {
9 | @JvmStatic
10 | fun main(args: Array) {
11 | println(IsHappy().isHappy(19))
12 | println(IsHappy().isHappy(2))
13 | }
14 | }
15 |
16 | fun isHappy(n: Int): Boolean {
17 | val map = hashSetOf()
18 | var temp = n
19 | while (temp != 1 && !map.contains(temp)) {
20 | map.add(temp)
21 | temp = getNext(temp)
22 | }
23 | return temp == 1
24 | }
25 |
26 | private fun getNext(n: Int): Int {
27 | var sum = 0
28 | var temp = n
29 | while (temp > 0) {
30 | val d = temp % 10
31 | temp /= 10
32 | sum += d * d
33 | }
34 | return sum
35 | }
36 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/IsIsomorphic.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | /**
4 | * 205. 同构字符串
5 | */
6 | class IsIsomorphic {
7 |
8 | companion object {
9 |
10 | @JvmStatic
11 | fun main(args: Array) {
12 | println(IsIsomorphic().isIsomorphic("egg", "add"))
13 | println(IsIsomorphic().isIsomorphic("foo", "bar"))
14 | }
15 | }
16 |
17 | fun isIsomorphic(s: String, t: String): Boolean {
18 | val s2t = hashMapOf()
19 | val t2s = hashMapOf()
20 |
21 | for (i in s.indices) {
22 | val x = s[i]
23 | val y = t[i]
24 | if (s2t.containsKey(x) && s2t[x] != y || t2s.containsKey(y) && t2s[y] != x) {
25 | return false
26 | }
27 | s2t[x] = y
28 | t2s[y] = x
29 | }
30 | return true
31 | }
32 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/IsPalindrome.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | /**
4 | * 9. 回文数
5 | *
6 | * 给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
7 | *
8 | * 回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
9 | * 例如,121 是回文,而 123 不是。
10 | *
11 | * 示例 1:
12 | * 输入:x = 121
13 | * 输出:true
14 | *
15 | * 示例2:
16 | * 输入:x = -121
17 | * 输出:false
18 | * 解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
19 | *
20 | * 示例 3:
21 | * 输入:x = 10
22 | * 输出:false
23 | * 解释:从右向左读, 为 01 。因此它不是一个回文数。
24 | */
25 | class IsPalindrome {
26 | companion object {
27 |
28 | @JvmStatic
29 | fun main(args: Array) {
30 | println(IsPalindrome().isPalindrome(121))
31 | println(IsPalindrome().isPalindrome(-121))
32 | println(IsPalindrome().isPalindrome(10))
33 | }
34 |
35 | }
36 |
37 | fun isPalindrome(x: Int): Boolean {
38 | if (x < 0) return false
39 | if (x % 10 == 0 && x != 0) return false
40 | var temp = x
41 | var reverse = 0
42 |
43 | while (temp > reverse) {
44 | reverse = temp % 10 + reverse * 10
45 | temp /= 10
46 | }
47 |
48 | return reverse == temp || reverse / 10 == temp
49 | }
50 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/IsPowerOfTwo.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | /**
4 | * 231. 2 的幂
5 | */
6 | class IsPowerOfTwo {
7 |
8 | companion object {
9 |
10 | @JvmStatic
11 | fun main(args: Array) {
12 | println(IsPowerOfTwo().isPowerOfTwo(1))
13 | println(IsPowerOfTwo().isPowerOfTwo(16))
14 | println(IsPowerOfTwo().isPowerOfTwo(3))
15 | println(IsPowerOfTwo().isPowerOfTwo(4))
16 | }
17 |
18 | }
19 |
20 | fun isPowerOfTwo(n: Int): Boolean {
21 | return n > 0 && n.and(n - 1) == 0
22 | }
23 |
24 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/IsSameTree.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | /**
4 | * 100. 相同的树
5 | */
6 | class IsSameTree {
7 |
8 | companion object {
9 | @JvmStatic
10 | fun main(args: Array) {
11 | println(IsSameTree().isSameTree(TreeNode(1).apply {
12 | left = TreeNode(2)
13 | right = TreeNode(3)
14 | },TreeNode(1).apply {
15 | left = TreeNode(2)
16 | right = TreeNode(3)
17 | }))
18 | println(IsSameTree().isSameTree(TreeNode(1).apply {
19 | left = TreeNode(2)
20 | },TreeNode(1).apply {
21 | right = TreeNode(3)
22 | }))
23 | }
24 | }
25 |
26 | fun isSameTree(p: TreeNode?, q: TreeNode?): Boolean {
27 | if (p == null && q == null) return true
28 | if (p == null || q == null) return false
29 | if (p.`val` != q.`val`) return false
30 | return isSameTree(p.left, q.left) && isSameTree(p.right, q.right)
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/IsSymmetric.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | /**
4 | * 101. 对称二叉树
5 | */
6 | class IsSymmetric {
7 |
8 | companion object {
9 | @JvmStatic
10 | fun main(args: Array) {
11 | println(IsSymmetric().isSymmetric(TreeNode(1).apply {
12 | left = TreeNode(2).apply {
13 | left = TreeNode(3)
14 | right = TreeNode(4)
15 | }
16 | right = TreeNode(2).apply {
17 | left = TreeNode(4)
18 | right = TreeNode(3)
19 | }
20 | }))
21 |
22 | println(IsSymmetric().isSymmetric(TreeNode(1).apply {
23 | left = TreeNode(2).apply {
24 | right = TreeNode(3)
25 | }
26 | right = TreeNode(2).apply {
27 | right = TreeNode(3)
28 | }
29 | }))
30 | }
31 | }
32 |
33 | fun isSymmetric(root: TreeNode?): Boolean {
34 | return check(root, root)
35 | }
36 |
37 | private fun check(p: TreeNode?, q: TreeNode?): Boolean {
38 | if (p == null && q == null) return true
39 | if (p == null || q == null) return false
40 |
41 | return p.`val` == q.`val` && check(p.left, q.right) && check(p.right, q.left)
42 | }
43 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/IsValid.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | import java.util.*
4 |
5 | /**
6 | * 20. 有效的括号
7 | * 给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。
8 | *
9 | * 有效字符串需满足:
10 | * 1. 左括号必须用相同类型的右括号闭合。
11 | * 2. 左括号必须以正确的顺序闭合。
12 | */
13 | class IsValid {
14 |
15 | companion object {
16 | @JvmStatic
17 | fun main(args: Array) {
18 | println(IsValid().isValid("()"))
19 | println(IsValid().isValid("()[]{}"))
20 | println(IsValid().isValid("(]"))
21 | println(IsValid().isValid("{[]}"))
22 | }
23 | }
24 |
25 | // {[]}
26 | // ()[]{}
27 | fun isValid(s: String): Boolean {
28 | val length = s.length
29 | var i = 0
30 | val stack = Stack()
31 | while (i < length) {
32 | val char = s[i++]
33 | if (char == '(' || char == '[' || char == '{') {
34 | stack.push(char)
35 | } else if (stack.isEmpty() || (char == ')' && stack.peek() != '(') || (char == ']' && stack.peek() != '[') || (char == '}' && stack.peek() != '{')) {
36 | return false
37 | } else {
38 | stack.pop()
39 | }
40 | }
41 | return stack.isEmpty() // notice
42 | }
43 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/LongestCommonPrefix.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | /**
4 | * 14. 最长公共前缀
5 | *
6 | * 编写一个函数来查找字符串数组中的最长公共前缀。
7 | * 如果不存在公共前缀,返回空字符串 ""。
8 | *
9 | * 示例 1:
10 | *
11 | * 输入:strs = ["flower","flow","flight"]
12 | * 输出:"fl"
13 | * 示例 2:
14 | *
15 | * 输入:strs = ["dog","racecar","car"]
16 | * 输出:""
17 | * 解释:输入不存在公共前缀。
18 | */
19 | class LongestCommonPrefix {
20 |
21 | companion object {
22 | @JvmStatic
23 | fun main(args: Array) {
24 | println(
25 | LongestCommonPrefix().longestCommonPrefix(
26 | arrayOf(
27 | "flower", "flow", "flight"
28 | )
29 | )
30 | )
31 | println(
32 | LongestCommonPrefix().longestCommonPrefix(
33 | arrayOf(
34 | "dog", "racecar", "car"
35 | )
36 | )
37 | )
38 | }
39 | }
40 |
41 | fun longestCommonPrefix(strs: Array): String {
42 | if (strs.isEmpty()) return ""
43 |
44 | var result = strs[0]
45 |
46 | for (i in 1 until strs.size) {
47 | val length = Math.min(result.length, strs[i].length)
48 | var j = 0
49 | while (j < length && result[j] == strs[i][j]) {
50 | j++
51 | }
52 | result = result.substring(0, j)
53 | if (result.isEmpty()) break
54 | }
55 |
56 | return result
57 | }
58 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/MajorityElement.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | /**
4 | * 169. 多数元素
5 | */
6 | class MajorityElement {
7 |
8 | companion object {
9 | @JvmStatic
10 | fun main(args: Array) {
11 | println(MajorityElement().majorityElement(intArrayOf(3, 2, 3)))
12 | println(MajorityElement().majorityElement(intArrayOf(2, 2, 1, 1, 1, 2, 2)))
13 | }
14 | }
15 |
16 | fun majorityElement(nums: IntArray): Int {
17 | nums.sort()
18 | return nums[nums.size / 2]
19 | }
20 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/MergeTwoLists.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | import com.daily.algothrim.leetcode.ListNode
4 |
5 | /**
6 | * 21. 合并两个有序链表
7 | *
8 | * 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
9 | */
10 | class MergeTwoLists {
11 |
12 | companion object {
13 | @JvmStatic
14 | fun main(args: Array) {
15 | MergeTwoLists().mergeTwoLists(ListNode(1).apply {
16 | next = ListNode(2).apply {
17 | next = ListNode(4)
18 | }
19 | }, ListNode(1).apply {
20 | next = ListNode(3).apply {
21 | next = ListNode(4)
22 | }
23 | })?.printAll()
24 | MergeTwoLists().mergeTwoLists(null, null)?.printAll()
25 | MergeTwoLists().mergeTwoLists(null, ListNode(0))?.printAll()
26 | }
27 | }
28 |
29 | // l1 = [1,2,4], l2 = [1,3,4]
30 | // [1,1,2,3,4,4]
31 | fun mergeTwoLists(l1: ListNode?, l2: ListNode?): ListNode? {
32 | val result = ListNode(-1)
33 | var temp: ListNode? = result
34 | var left = l1
35 | var right = l2
36 |
37 | while (left != null && right != null) {
38 | if (left.`val` <= right.`val`) {
39 | temp?.next = left
40 | left = left.next
41 | } else {
42 | temp?.next = right
43 | right = right.next
44 | }
45 | temp = temp?.next
46 | }
47 |
48 | if (left != null) {
49 | temp?.next = left
50 | }
51 |
52 | if (right != null) {
53 | temp?.next = right
54 | }
55 |
56 | return result.next
57 | }
58 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/MyQueue.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | import java.util.Stack
4 |
5 | /**
6 | * 232. 用栈实现队列
7 | */
8 | class MyQueue {
9 |
10 | companion object {
11 |
12 | @JvmStatic
13 | fun main(args: Array) {
14 | MyQueue().apply {
15 | push(1)
16 | push(2)
17 | println(peek())
18 | println(pop())
19 | println(empty())
20 | }
21 | }
22 |
23 | }
24 |
25 | private val inStack = Stack()
26 | private val outStack = Stack()
27 |
28 | fun push(x: Int) {
29 | inStack.push(x)
30 | }
31 |
32 | fun pop(): Int {
33 | in2out()
34 | return outStack.pop()
35 | }
36 |
37 | fun peek(): Int {
38 | in2out()
39 | return outStack.peek()
40 | }
41 |
42 | fun empty(): Boolean {
43 | return inStack.isEmpty() && outStack.isEmpty()
44 | }
45 |
46 | private fun in2out() {
47 | if (outStack.isEmpty()) {
48 | while (inStack.isNotEmpty()) {
49 | outStack.push(inStack.pop())
50 | }
51 | }
52 | }
53 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/MySqrt.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | /**
4 | * 69. x 的平方根
5 | *
6 | * 给你一个非负整数 x ,计算并返回 x 的 算术平方根 。
7 | * 由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
8 | * 注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。
9 | *
10 | * 示例 1:
11 | * 输入:x = 4
12 | * 输出:2
13 | *
14 | * 示例 2:
15 | * 输入:x = 8
16 | * 输出:2
17 | * 解释:8 的算术平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。
18 | */
19 | class MySqrt {
20 | companion object {
21 | @JvmStatic
22 | fun main(args: Array) {
23 | println(MySqrt().mySqrt(4))
24 | println(MySqrt().mySqrt(8))
25 | println(MySqrt().mySqrt(2147395599))
26 | }
27 | }
28 |
29 | fun mySqrt(x: Int): Int {
30 | var l = 0
31 | var r = x
32 | var ans = -1
33 |
34 | while (l <= r) {
35 | val mid = l + (r - l).shr(1)
36 | if (mid * mid.toLong() <= x) {
37 | ans = mid
38 | l = mid + 1
39 | } else {
40 | r = mid - 1
41 | }
42 | }
43 | return ans
44 | }
45 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/MyStack.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | import java.util.LinkedList
4 |
5 | /**
6 | * 225. 用队列实现栈
7 | */
8 | class MyStack {
9 |
10 | companion object {
11 | @JvmStatic
12 | fun main(args: Array) {
13 | MyStack().apply {
14 | push(1)
15 | push(2)
16 | println(top())
17 | println(pop())
18 | println(empty())
19 | }
20 | }
21 | }
22 |
23 | private var queue1: LinkedList = LinkedList()
24 | private var queue2: LinkedList = LinkedList()
25 |
26 | fun push(x: Int) {
27 | queue1.offer(x)
28 | while (queue2.isNotEmpty()) {
29 | queue1.offer(queue2.poll())
30 | }
31 | val temp = queue1
32 | queue1 = queue2
33 | queue2 = temp
34 | }
35 |
36 | fun pop(): Int {
37 | return queue2.poll()
38 | }
39 |
40 | fun top(): Int {
41 | return queue2.peek()
42 | }
43 |
44 | fun empty(): Boolean {
45 | return queue2.isEmpty()
46 | }
47 |
48 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/PlusOne.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | /**
4 | * 66. 加一
5 | *
6 | * 给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。
7 | * 最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。
8 | * 你可以假设除了整数 0 之外,这个整数不会以零开头。
9 | *
10 | * 示例 1:
11 | * 输入:digits = [1,2,3]
12 | * 输出:[1,2,4]
13 | * 解释:输入数组表示数字 123。
14 | *
15 | * 示例 2:
16 | * 输入:digits = [4,3,2,1]
17 | * 输出:[4,3,2,2]
18 | * 解释:输入数组表示数字 4321。
19 | *
20 | * 示例 3:
21 | * 输入:digits = [0]
22 | * 输出:[1]
23 | */
24 | class PlusOne {
25 |
26 | companion object {
27 | @JvmStatic
28 | fun main(args: Array) {
29 | PlusOne().plusOne(intArrayOf(1, 2, 3)).forEach {
30 | print(it)
31 | }
32 | println()
33 | PlusOne().plusOne(intArrayOf(4, 3, 2, 1)).forEach {
34 | print(it)
35 | }
36 | println()
37 | PlusOne().plusOne(intArrayOf(0)).forEach {
38 | print(it)
39 | }
40 | }
41 | }
42 |
43 | fun plusOne(digits: IntArray): IntArray {
44 | val size = digits.size
45 | for (i in size - 1 downTo 0) {
46 | if (digits[i] != 9) {
47 | digits[i]++
48 | for (j in i + 1 until size) {
49 | digits[j] = 0
50 | }
51 | return digits
52 | }
53 | }
54 | val result = IntArray(size + 1)
55 | result[0] = 1
56 | return result
57 | }
58 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/PostorderTraversal.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | /**
4 | * 145. 二叉树的后序遍历
5 | */
6 | class PostorderTraversal {
7 |
8 | companion object {
9 | @JvmStatic
10 | fun main(args: Array) {
11 | PostorderTraversal().postorderTraversal(TreeNode(1).apply {
12 | right = TreeNode(2).apply {
13 | left = TreeNode(3)
14 | }
15 | }).forEach {
16 | print(it)
17 | }
18 | println()
19 | PostorderTraversal().postorderTraversal(TreeNode(1).apply {
20 | right = TreeNode(2)
21 | }).forEach {
22 | print(it)
23 | }
24 | println()
25 | }
26 | }
27 |
28 | fun postorderTraversal(root: TreeNode?): List {
29 | val result = mutableListOf()
30 | postorder(root, result)
31 | return result
32 | }
33 |
34 | private fun postorder(root: TreeNode?, list: MutableList) {
35 | if (root == null) return
36 | postorder(root.left, list)
37 | postorder(root.right, list)
38 | list.add(root.`val`)
39 | }
40 |
41 | class TreeNode(var `val`: Int) {
42 | var left: TreeNode? = null
43 | var right: TreeNode? = null
44 | }
45 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/PreorderTraversal.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | /**
4 | * 144. 二叉树的前序遍历
5 | */
6 | class PreorderTraversal {
7 |
8 | companion object {
9 | @JvmStatic
10 | fun main(args: Array) {
11 | PreorderTraversal().preorderTraversal(TreeNode(1).apply {
12 | right = TreeNode(2).apply {
13 | left = TreeNode(3)
14 | }
15 | }).forEach {
16 | print(it)
17 | }
18 | println()
19 | PreorderTraversal().preorderTraversal(TreeNode(1).apply {
20 | right = TreeNode(2)
21 | }).forEach {
22 | print(it)
23 | }
24 | println()
25 | }
26 | }
27 |
28 | fun preorderTraversal(root: TreeNode?): List {
29 | val result = mutableListOf()
30 | preorder(root, result)
31 | return result
32 | }
33 |
34 | private fun preorder(root: TreeNode?, list: MutableList) {
35 | if (root == null) return
36 | list.add(root.`val`)
37 | preorder(root.left, list)
38 | preorder(root.right, list)
39 | }
40 |
41 | class TreeNode(var `val`: Int) {
42 | var left: TreeNode? = null
43 | var right: TreeNode? = null
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/RemoveDuplicates.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | /**
4 | * 26. 删除有序数组中的重复项
5 | *
6 | * 给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。
7 | * 由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么nums的前 k 个元素应该保存最终结果。
8 | * 将最终结果插入nums 的前 k 个位置后返回 k 。
9 | * 不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
10 | *
11 | * 示例 1:
12 | * 输入:nums = [1,1,2]
13 | * 输出:2, nums = [1,2,_]
14 | * 解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。
15 | *
16 | * 示例 2:
17 | * 输入:nums = [0,0,1,1,1,2,2,3,3,4]
18 | * 输出:5, nums = [0,1,2,3,4]
19 | * 解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。
20 | */
21 | class RemoveDuplicates {
22 |
23 | companion object {
24 | @JvmStatic
25 | fun main(args: Array) {
26 | println(
27 | RemoveDuplicates().removeDuplicates(
28 | intArrayOf(1, 1, 2)
29 | )
30 | )
31 | println(
32 | RemoveDuplicates().removeDuplicates(
33 | intArrayOf(0, 0, 1, 1, 1, 2, 2, 3, 3, 4)
34 | )
35 | )
36 | }
37 | }
38 |
39 | fun removeDuplicates(nums: IntArray): Int {
40 | if (nums.isEmpty()) return 0
41 |
42 | var slow = 1
43 | var fast = 1
44 |
45 | while (fast < nums.size) {
46 | if (nums[fast] != nums[fast - 1]) {
47 | nums[slow] = nums[fast]
48 | slow++
49 | }
50 | fast++
51 | }
52 | return slow
53 | }
54 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/RemoveElement.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | /**
4 | * 27. 移除元素
5 | * 给你一个数组 nums和一个值 val,你需要 原地 移除所有数值等于val的元素,并返回移除后数组的新长度。
6 | * 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
7 | * 元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
8 | *
9 | * 示例 1:
10 | * 输入:nums = [3,2,2,3], val = 3
11 | * 输出:2, nums = [2,2]
12 | * 解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。
13 | *
14 | * 示例 2:
15 | * 输入:nums = [0,1,2,2,3,0,4,2], val = 2
16 | * 输出:5, nums = [0,1,4,0,3]
17 | * 解释:函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。
18 | */
19 | class RemoveElement {
20 |
21 | companion object {
22 | @JvmStatic
23 | fun main(args: Array) {
24 | println(RemoveElement().removeElement(
25 | intArrayOf(3,2,2,3), 3
26 | ))
27 | println(RemoveElement().removeElement(
28 | intArrayOf(0,1,2,2,3,0,4,2), 2
29 | ))
30 | }
31 | }
32 |
33 | fun removeElement(nums: IntArray, `val`: Int): Int {
34 | var left = 0
35 | var right = nums.size
36 |
37 | while (left < right) {
38 | if (nums[left] == `val`) {
39 | nums[left] = nums[right - 1]
40 | right--
41 | } else {
42 | left++
43 | }
44 | }
45 | return left
46 | }
47 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/Reverse.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | /**
4 | * 7. 整数反转
5 | *
6 | * 给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。
7 | *
8 | * 如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。
9 | *
10 | * 假设环境不允许存储 64 位整数(有符号或无符号)。
11 | */
12 | class Reverse {
13 |
14 | companion object {
15 | @JvmStatic
16 | fun main(args: Array) {
17 | println(Reverse().reverse(123))
18 | println(Reverse().reverse(-123))
19 | println(Reverse().reverse(120))
20 | println(Reverse().reverse(0))
21 | }
22 | }
23 |
24 | // 输入:x = 123
25 | // 输出:321
26 | // 时间复杂度:O(\log |x|)O(log∣x∣)。翻转的次数即 xx 十进制的位数。
27 | // 空间复杂度:O(1)O(1)。
28 | fun reverse(x: Int): Int {
29 | var k = x
30 | var temp: Int
31 | var result = 0
32 | while (k != 0) {
33 | if (result > Int.MAX_VALUE / 10 || result < Int.MIN_VALUE / 10) return 0
34 | temp = k % 10
35 | k /= 10
36 | result = result * 10 + temp
37 | }
38 | return result
39 | }
40 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/SearchInsert.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | /**
4 | * 35. 搜索插入位置
5 | * 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
6 | * 请必须使用时间复杂度为 O(log n) 的算法。
7 | *
8 | * 示例 1:
9 | * 输入: nums = [1,3,5,6], target = 5
10 | * 输出: 2
11 | *
12 | * 示例 2:
13 | * 输入: nums = [1,3,5,6], target = 2
14 | * 输出: 1
15 | *
16 | * 示例 3:
17 | * 输入: nums = [1,3,5,6], target = 7
18 | * 输出: 4
19 | */
20 | class SearchInsert {
21 |
22 | companion object {
23 | @JvmStatic
24 | fun main(args: Array) {
25 | println(SearchInsert().searchInsert(intArrayOf(1,3,5,6), 5))
26 | println(SearchInsert().searchInsert(intArrayOf(1,3,5,6), 2))
27 | println(SearchInsert().searchInsert(intArrayOf(1,3,5,6), 7))
28 | }
29 | }
30 |
31 | fun searchInsert(nums: IntArray, target: Int): Int {
32 | var left = 0
33 | var right = nums.size - 1
34 |
35 | while (left <= right) {
36 | val mid = left + (right - left).shr(1)
37 | if (target <= nums[mid]) {
38 | right = mid - 1
39 | } else {
40 | left = mid + 1
41 | }
42 | }
43 | return left
44 | }
45 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/easy/SingleNumber.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.easy
2 |
3 | /**
4 | * 136. 只出现一次的数字
5 | */
6 | class SingleNumber {
7 | companion object {
8 | @JvmStatic
9 | fun main(args: Array) {
10 | println(SingleNumber().singleNumber(intArrayOf(2, 2, 1)))
11 | println(SingleNumber().singleNumber(intArrayOf(4, 1, 2, 1, 2)))
12 | }
13 | }
14 |
15 | fun singleNumber(nums: IntArray): Int {
16 | var result = 0
17 | nums.forEach {
18 | result = result.xor(it)
19 | }
20 | return result
21 | }
22 |
23 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/hard/LargestRectangleArea.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.hard
2 |
3 | import java.util.*
4 |
5 | /**
6 | * 84. 柱状图中最大的矩形
7 | *
8 | * 给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
9 | * 求在该柱状图中,能够勾勒出来的矩形的最大面积。
10 | */
11 | class LargestRectangleArea {
12 |
13 | companion object {
14 |
15 | @JvmStatic
16 | fun main(args: Array) {
17 | println(LargestRectangleArea().largestRectangleArea(intArrayOf(2, 1, 5, 6, 2, 3)))
18 | println(LargestRectangleArea().largestRectangleArea(intArrayOf(2, 4)))
19 | }
20 | }
21 |
22 | // 输入:heights = [2,1,5,6,2,3]
23 | // 输出:10
24 | fun largestRectangleArea(heights: IntArray): Int {
25 | var largest = Int.MIN_VALUE
26 | val size = heights.size
27 | val left = IntArray(size)
28 | val right = IntArray(size)
29 | Arrays.fill(right, size)
30 |
31 | val stack = Stack()
32 | for (i in 0 until size) {
33 | while (stack.isNotEmpty() && heights[stack.peek()] >= heights[i]) {
34 | right[stack.peek()] = i
35 | stack.pop()
36 | }
37 | left[i] = if (stack.isEmpty()) -1 else stack.peek()
38 | stack.push(i)
39 | }
40 |
41 | for (j in 0 until size) {
42 | largest = Math.max(largest, (right[j] - left[j] - 1) * heights[j])
43 | }
44 |
45 | return largest
46 | }
47 |
48 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/hard/LongestValidParentheses.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.hard
2 |
3 | import java.util.*
4 |
5 | /**
6 | * 32. 最长有效括号
7 | *
8 | * 给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。
9 | */
10 | class LongestValidParentheses {
11 |
12 | companion object {
13 | @JvmStatic
14 | fun main(args: Array) {
15 | println(LongestValidParentheses().longestValidParentheses("(()"))
16 | println(LongestValidParentheses().longestValidParentheses(")()())"))
17 | println(LongestValidParentheses().longestValidParentheses(""))
18 | println(LongestValidParentheses().longestValidParentheses("()(()"))
19 | }
20 | }
21 |
22 | // s = ")()())"
23 | // 4
24 | fun longestValidParentheses(s: String): Int {
25 | val stack = Stack()
26 | stack.push(-1)
27 | val length = s.length
28 | var i = 0
29 | var max = 0
30 |
31 | while (i < length) {
32 | if (s[i] == ')') {
33 | stack.pop()
34 | if (stack.isNotEmpty()) {
35 | max = Math.max(max, i - stack.peek())
36 | } else {
37 | stack.push(i)
38 | }
39 | } else {
40 | stack.push(i)
41 | }
42 | i++
43 | }
44 |
45 | return max
46 | }
47 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/hard/MissingTwo.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.hard
2 |
3 | /**
4 | * 给定一个数组,包含从 1 到 N 所有的整数,但其中缺了两个数字。你能在 O(N) 时间内只用 O(1) 的空间找到它们吗?
5 | * 以任意顺序返回这两个数字均可。
6 | *
7 | * 示例 1:
8 | * 输入: [1]
9 | * 输出: [2,3]
10 | * 示例 2:
11 | *
12 | * 输入: [2,3]
13 | * 输出: [1,4]
14 | *
15 | * 提示:
16 | * nums.length <= 30000
17 | */
18 | class MissingTwo {
19 |
20 | companion object {
21 | @JvmStatic
22 | fun main(args: Array) {
23 | MissingTwo().missingTwo(intArrayOf(1)).apply {
24 | println("${this[0]} ${this[1]}")
25 | }
26 | MissingTwo().missingTwo(intArrayOf(2, 3)).apply {
27 | println("${this[0]} ${this[1]}")
28 | }
29 | println("${2.xor(-2)}")
30 | }
31 | }
32 |
33 | fun missingTwo(nums: IntArray): IntArray {
34 | var xor = 0
35 |
36 | // n - 2
37 | for (i in nums) {
38 | xor = xor.xor(i)
39 | }
40 | val n = nums.size + 2
41 | // n
42 | for (i in 1 .. n) {
43 | xor = xor.xor(i)
44 | }
45 |
46 | val lsb = xor.and(-xor)
47 |
48 | var value1 = 0
49 | var value2 = 0
50 | // n - 2
51 | for (i in nums) {
52 | if (lsb.and(i) != 0) {
53 | value1 = value1.xor(i)
54 | } else {
55 | value2 = value2.xor(i)
56 | }
57 | }
58 |
59 | // n
60 | for (i in 1..n) {
61 | if (lsb.and(i) != 0) {
62 | value1 = value1.xor(i)
63 | } else {
64 | value2 = value2.xor(i)
65 | }
66 | }
67 |
68 | return intArrayOf(value1, value2)
69 | }
70 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/medium/CanJump.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.medium
2 |
3 | /**
4 | * 55. 跳跃游戏
5 | * 给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。
6 | *
7 | * 数组中的每个元素代表你在该位置可以跳跃的最大长度。
8 | * 判断你是否能够到达最后一个下标。
9 | *
10 | */
11 | class CanJump {
12 |
13 | companion object {
14 | @JvmStatic
15 | fun main(args: Array) {
16 | println(CanJump().canJump(intArrayOf(2, 3, 1, 1, 5)))
17 | println(CanJump().canJump(intArrayOf(3, 2, 1, 0, 4)))
18 | println(CanJump().canJump2(intArrayOf(2, 3, 1, 1, 5)))
19 | println(CanJump().canJump2(intArrayOf(3, 2, 1, 0, 4)))
20 | }
21 | }
22 |
23 | fun canJump(nums: IntArray): Boolean {
24 | val size = nums.size
25 |
26 | var i = size - 2
27 | nums[size - 1] = -1
28 | while (i >= 0) {
29 | var step = nums[i]
30 | while (step >= 0) {
31 | if (i + step < size && nums[i + step] == -1) {
32 | nums[i] = -1
33 | break
34 | }
35 | step--
36 | }
37 | i--
38 | }
39 | return nums[0] == -1
40 | }
41 |
42 | /**
43 | * greed
44 | */
45 | fun canJump2(nums: IntArray): Boolean {
46 | val size = nums.size
47 | var maxJump = 0
48 | var i = 0
49 | while (i < size) {
50 | if (i <= maxJump) {
51 | maxJump = Math.max(i + nums[i], maxJump)
52 | if (maxJump >= size - 1) {
53 | return true
54 | }
55 | }
56 | i++
57 | }
58 | return false
59 | }
60 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/medium/Convert.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.medium
2 |
3 | /**
4 | * 6. Z 字形变换
5 | */
6 | class Convert {
7 |
8 | companion object {
9 |
10 | @JvmStatic
11 | fun main(args: Array) {
12 | println(Convert().convert("PAYPALISHIRING", 3))
13 | println(Convert().convert("PAYPALISHIRING", 4))
14 | }
15 | }
16 |
17 | fun convert(s: String, numRows: Int): String {
18 | val n = s.length
19 | if (numRows == 1 || n <= numRows) return s
20 |
21 | val p = numRows + numRows - 2
22 | val pc = numRows - 1
23 | val column = (n + p - 1) / p * pc
24 |
25 | val matrix = Array(numRows) {
26 | CharArray(column) {
27 | '0'
28 | }
29 | }
30 |
31 | var x = 0
32 | var y = 0
33 |
34 | for (i in 0 until n) {
35 | matrix[x][y] = s[i]
36 | if (i % p < numRows - 1) {
37 | x++
38 | } else {
39 | x--
40 | y++
41 | }
42 | }
43 |
44 | val result = StringBuilder()
45 | for (j in 0 until numRows) {
46 | for (k in 0 until column) {
47 | if (matrix[j][k] != '0') {
48 | result.append(matrix[j][k])
49 | }
50 | }
51 | }
52 | return result.toString()
53 | }
54 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/medium/CountAndSay.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.medium
2 |
3 | import java.lang.StringBuilder
4 |
5 | /**
6 | * 38. 外观数列
7 | */
8 | class CountAndSay {
9 |
10 | companion object {
11 |
12 | @JvmStatic
13 | fun main(args: Array) {
14 | println(CountAndSay().countAndSay(1))
15 | println(CountAndSay().countAndSay(4))
16 | }
17 | }
18 |
19 | fun countAndSay(n: Int): String {
20 | var str = "1"
21 | for (i in 2..n) {
22 | val sb = StringBuilder()
23 | var start = 0
24 | var curr = 0
25 | while (curr < str.length) {
26 | while (curr < str.length && str[curr] == str[start]) {
27 | curr++
28 | }
29 | sb.append(curr - start).append(str[start])
30 | start = curr
31 | }
32 | str = sb.toString()
33 | }
34 | return str
35 | }
36 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/medium/GenerateParenthesis.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.medium
2 |
3 | /**
4 | * 22. 括号生成
5 | *
6 | * 数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
7 | */
8 | class GenerateParenthesis {
9 |
10 | companion object {
11 | @JvmStatic
12 | fun main(args: Array) {
13 | GenerateParenthesis().generateParenthesis(3).forEach {
14 | println(it)
15 | }
16 | }
17 | }
18 |
19 | // n = 3
20 | // ["((()))","(()())","(())()","()(())","()()()"]
21 | fun generateParenthesis(n: Int): List {
22 | val result = arrayListOf()
23 | backtracking(StringBuilder(), 0, 0, n, result)
24 | return result
25 | }
26 |
27 | private fun backtracking(currentStr: StringBuilder, left: Int, right: Int, n: Int, result: ArrayList) {
28 | if (currentStr.length == 2 * n) {
29 | result.add(currentStr.toString())
30 | return
31 | }
32 |
33 | if (left < n) {
34 | currentStr.append("(")
35 | backtracking(currentStr, left + 1, right, n, result)
36 | currentStr.deleteCharAt(currentStr.length - 1)
37 | }
38 | if (right < left) {
39 | currentStr.append(")")
40 | backtracking(currentStr, left, right + 1, n, result)
41 | currentStr.deleteCharAt(currentStr.length - 1)
42 | }
43 |
44 | }
45 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/medium/IntToRoman.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.medium
2 |
3 | /**
4 | * 12. 整数转罗马数字
5 | */
6 | class IntToRoman {
7 |
8 | companion object {
9 | @JvmStatic
10 | fun main(args: Array) {
11 | println(IntToRoman().intToRoman(1994))
12 | }
13 | }
14 |
15 | private val values = arrayOf(
16 | 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1
17 | )
18 |
19 | private val symbols = arrayOf(
20 | "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"
21 | )
22 |
23 | fun intToRoman(num: Int): String {
24 | var temp = num
25 | return StringBuffer().apply {
26 | values.forEachIndexed { index, value ->
27 | val symbol = symbols[index]
28 | while (temp >= value) {
29 | temp -= value
30 | append(symbol)
31 | }
32 | if (temp == 0) return@apply
33 | }
34 | }.toString()
35 | }
36 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/medium/Jump.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.medium
2 |
3 | /**
4 | * 45. 跳跃游戏 II
5 | */
6 | class Jump {
7 |
8 | companion object {
9 |
10 | @JvmStatic
11 | fun main(array: Array) {
12 | println(Jump().jump(intArrayOf(2,3,1,1,4)))
13 | println(Jump().jump(intArrayOf(2,3,0,1,4)))
14 | }
15 | }
16 |
17 | fun jump(nums: IntArray): Int {
18 | val size = nums.size
19 |
20 | var maxPosition = 0
21 | var end = 0
22 | var step = 0
23 |
24 | for (i in 0 until size - 1) {
25 | maxPosition = Math.max(maxPosition, i + nums[i])
26 | if (i == end) {
27 | end = maxPosition
28 | step++
29 | }
30 | }
31 | return step
32 | }
33 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/medium/LongestPalindrome.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.medium
2 |
3 | /**
4 | * 5. 最长回文子串
5 | * 给你一个字符串 s,找到 s 中最长的回文子串。
6 | */
7 | class LongestPalindrome {
8 |
9 | companion object {
10 | @JvmStatic
11 | fun main(args: Array) {
12 | println(LongestPalindrome().longestPalindrome("babad"))
13 | println(LongestPalindrome().longestPalindrome("cbbd"))
14 | println(LongestPalindrome().longestPalindrome("a"))
15 | println(LongestPalindrome().longestPalindrome("ac"))
16 | println(LongestPalindrome().longestPalindrome("ccc"))
17 | }
18 | }
19 |
20 | var finalStart = 0
21 | var finalEnd = 0
22 | var maxLength = 0
23 |
24 | fun longestPalindrome(s: String): String {
25 | val length = s.length
26 | s.forEachIndexed { index, _ ->
27 | checkPalindrome(s, index, index)
28 | if (index + 1 < length) {
29 | checkPalindrome(s, index, index + 1)
30 | }
31 | }
32 | return s.substring(finalStart, finalEnd + 1)
33 | }
34 |
35 | private fun checkPalindrome(s: String, left: Int, right: Int) {
36 | val length = s.length
37 | var start = left
38 | var end = right
39 | while (start >= 0 && end < length) {
40 | if (s[start] == s[end]) {
41 | start--
42 | end++
43 | continue
44 | }
45 | break
46 | }
47 | end--
48 | start++
49 | if (end - start + 1 > maxLength) {
50 | maxLength = end - start + 1
51 | finalStart = start
52 | finalEnd = end
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/medium/MaxArea.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.medium
2 |
3 | /**
4 | * 11. 盛最多水的容器
5 | * 给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
6 | */
7 | class MaxArea {
8 |
9 | companion object {
10 | @JvmStatic
11 | fun main(args: Array) {
12 | println(MaxArea().maxArea(intArrayOf(1, 8, 6, 2, 5, 4, 8, 3, 7)))
13 | println(MaxArea().maxArea(intArrayOf(1, 1)))
14 | println(MaxArea().maxArea(intArrayOf(4, 3, 2, 1, 4)))
15 | println(MaxArea().maxArea(intArrayOf(1, 2, 1)))
16 | }
17 | }
18 |
19 | // [1,8,6,2,5,4,8,3,7]
20 | fun maxArea(height: IntArray): Int {
21 | var start = 0
22 | var end = height.size - 1
23 | var max = 0
24 | var min = Int.MIN_VALUE
25 | while (start < end) {
26 | val startValue = height[start]
27 | val endValue = height[end]
28 | val minValue = Math.min(startValue, endValue)
29 | if (minValue > min) {
30 | min = minValue
31 | max = Math.max(max, (end - start) * min)
32 | }
33 | if (startValue <= min) {
34 | start++
35 | } else {
36 | end--
37 | }
38 | }
39 | return max
40 | }
41 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/medium/Merge.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.medium
2 |
3 | /**
4 | * 56. 合并区间
5 | *
6 | * 以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间。
7 | */
8 | class Merge {
9 |
10 | companion object {
11 | @JvmStatic
12 | fun main(args: Array) {
13 | Merge().merge(arrayOf(intArrayOf(1, 3), intArrayOf(2, 6), intArrayOf(8, 10), intArrayOf(15, 18))).forEach {
14 | println("${it[0]}, ${it[1]}")
15 | }
16 | Merge().merge(arrayOf(intArrayOf(1, 4), intArrayOf(0, 4))).forEach {
17 | println("${it[0]}, ${it[1]}")
18 | }
19 | }
20 | }
21 |
22 | // 输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
23 | // 输出:[[1,6],[8,10],[15,18]]
24 | // 解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
25 | fun merge(intervals: Array): Array {
26 | intervals.sortWith(Comparator { o1, o2 -> (o1?.get(0) ?: 0) - (o2?.get(0) ?: 0) })
27 |
28 | val result = arrayListOf()
29 | intervals.forEach {
30 | val start = it[0]
31 | val end = it[1]
32 | if (result.isEmpty() || result[result.size - 1][1] < start) {
33 | result.add(intArrayOf(start, end))
34 | } else {
35 | result[result.size - 1][1] = Math.max(result[result.size - 1][1], end)
36 | }
37 | }
38 | return result.toTypedArray()
39 | }
40 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/medium/MinPathSum.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.medium
2 |
3 | /**
4 | * 64. 最小路径和
5 | *
6 | * 给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
7 | * 说明:每次只能向下或者向右移动一步。
8 | */
9 | class MinPathSum {
10 |
11 | companion object {
12 | @JvmStatic
13 | fun main(args: Array) {
14 | println(
15 | MinPathSum().minPathSum(
16 | arrayOf(
17 | intArrayOf(1, 3, 1),
18 | intArrayOf(1, 5, 1),
19 | intArrayOf(4, 2, 1)
20 | )
21 | )
22 | )
23 | println(
24 | MinPathSum().minPathSum(
25 | arrayOf(
26 | intArrayOf(1, 2, 3),
27 | intArrayOf(4, 5, 6)
28 | )
29 | )
30 | )
31 | }
32 | }
33 |
34 | // 输入:grid = [[1,3,1],[1,5,1],[4,2,1]]
35 | // 输出:7
36 | // 解释:因为路径 1→3→1→1→1 的总和最小。
37 | fun minPathSum(grid: Array): Int {
38 | val r = grid.size
39 | val c = grid[0].size
40 | val minPath = Array(r) { IntArray(c) }
41 | minPath[0][0] = grid[0][0]
42 |
43 | for (i in 1 until r) {
44 | minPath[i][0] = minPath[i - 1][0] + grid[i][0]
45 | }
46 |
47 | for (j in 1 until c) {
48 | minPath[0][j] = minPath[0][j - 1] + grid[0][j]
49 | }
50 |
51 | for (i in 1 until r) {
52 | for (j in 1 until c) {
53 | minPath[i][j] = Math.min(minPath[i - 1][j], minPath[i][j - 1]) + grid[i][j]
54 | }
55 | }
56 |
57 | return minPath[r - 1][c - 1]
58 | }
59 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/medium/MyPow.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.medium
2 |
3 | /**
4 | * 50. Pow(x, n)
5 | */
6 | class MyPow {
7 |
8 | companion object {
9 | @JvmStatic
10 | fun main(args: Array) {
11 | println(MyPow().myPow(2.0, 10))
12 | println(MyPow().myPow(2.1, 3))
13 | println(MyPow().myPow(2.0, -2))
14 | }
15 | }
16 |
17 | fun myPow(x: Double, n: Int): Double {
18 | return if (n >= 0) quickMul(x, n) else 1.0 / quickMul(x, -n)
19 | }
20 |
21 | private fun quickMul(x: Double, n: Int): Double {
22 | if (n == 0) return 1.0
23 |
24 | val y = quickMul(x, n / 2)
25 | return if (n % 2 == 0) y * y else y * y * x
26 | }
27 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/medium/RemoveNthFromEnd.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.medium
2 |
3 | import com.daily.algothrim.leetcode.ListNode
4 |
5 | /**
6 | * 19. 删除链表的倒数第 N 个结点
7 | * 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
8 | * 进阶:你能尝试使用一趟扫描实现吗?
9 | */
10 | class RemoveNthFromEnd {
11 |
12 | companion object {
13 | @JvmStatic
14 | fun main(args: Array) {
15 | RemoveNthFromEnd().removeNthFromEnd(ListNode(1).apply {
16 | next = ListNode(2).apply {
17 | next = ListNode(3).apply {
18 | next = ListNode(4).apply {
19 | next = ListNode(5)
20 | }
21 | }
22 | }
23 | }, 2)?.printAll()
24 | }
25 | }
26 |
27 | // head = [1,2,3,4,5], n = 2
28 | fun removeNthFromEnd(head: ListNode?, n: Int): ListNode? {
29 | val result = ListNode(-1).apply { next = head }
30 | var slow: ListNode? = result
31 | var fast: ListNode? = result
32 |
33 | for (i in 0 until n) {
34 | fast = fast?.next
35 | }
36 |
37 | while (fast?.next != null) {
38 | slow = slow?.next
39 | fast = fast.next
40 |
41 | }
42 | slow?.next = slow?.next?.next
43 |
44 | return result.next
45 | }
46 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/medium/Rotate.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.medium
2 |
3 | /**
4 | * 48. 旋转图像
5 | *
6 | * 给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。
7 | * 你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。
8 | */
9 | class Rotate {
10 |
11 | companion object {
12 | @JvmStatic
13 | fun main(args: Array) {
14 | val matrix = arrayOf(
15 | intArrayOf(1, 2, 3),
16 | intArrayOf(4, 5, 6),
17 | intArrayOf(7, 8, 9))
18 | Rotate().rotate(matrix)
19 | matrix.forEach {
20 | it.forEach { item ->
21 | print(item)
22 | }
23 | println()
24 | }
25 | }
26 | }
27 |
28 | // matrix = [[1,2,3],[4,5,6],[7,8,9]] 1. i + 2 2. size - 1 , i + j
29 | // [[7,4,1],[8,5,2],[9,6,3]]
30 | // matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]]
31 | // [[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]
32 | fun rotate(matrix: Array) {
33 | val n = matrix.size
34 |
35 | // 水平翻转
36 | for (i in 0 until n / 2) {
37 | for (j in 0 until n) {
38 | val temp = matrix[i][j]
39 | matrix[i][j] = matrix[n - i - 1][j]
40 | matrix[n - i - 1][j] = temp
41 | }
42 | }
43 |
44 | // 主对角线翻转
45 | for (i in 0 until n) {
46 | for (j in 0 until i) {
47 | val temp = matrix[i][j]
48 | matrix[i][j] = matrix[j][i]
49 | matrix[j][i] = temp
50 | }
51 | }
52 | }
53 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/medium/Search.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.medium
2 |
3 | /**
4 | * 33. 搜索旋转排序数组
5 | *
6 | * 整数数组 nums 按升序排列,数组中的值 互不相同 。
7 | * 在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。
8 | * 给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。
9 | */
10 | class Search {
11 |
12 | companion object {
13 | @JvmStatic
14 | fun main(args: Array) {
15 | println(Search().search(intArrayOf(4, 5, 6, 7, 0, 1, 2), 0))
16 | println(Search().search(intArrayOf(4, 5, 6, 7, 0, 1, 2), 3))
17 | println(Search().search(intArrayOf(1), 0))
18 | println(Search().search(intArrayOf(3, 1), 1))
19 | }
20 | }
21 |
22 | fun search(nums: IntArray, target: Int): Int {
23 | var start = 0
24 | var end = nums.size - 1
25 |
26 | while (start <= end) {
27 | val mid = start + (end - start).shr(1)
28 | if (target == nums[mid]) return mid
29 | if (nums[start] <= nums[mid]) {
30 | if (target < nums[mid] && target >= nums[start]) {
31 | end = mid - 1
32 | } else {
33 | start = mid + 1
34 | }
35 | } else {
36 | if (target > nums[mid] && target <= nums[end]) {
37 | start = mid + 1
38 | } else {
39 | end = mid - 1
40 | }
41 | }
42 | }
43 | return -1
44 | }
45 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/medium/Subsets.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.medium
2 |
3 | /**
4 | * 78. 子集
5 | *
6 | * 给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
7 | * 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
8 | */
9 | class Subsets {
10 |
11 | companion object {
12 | @JvmStatic
13 | fun main(args: Array) {
14 | Subsets().subsets(intArrayOf(1, 2, 3)).forEach {
15 | it.forEach { item ->
16 | print(item)
17 | }
18 | println()
19 | }
20 | Subsets().subsets(intArrayOf(0)).forEach {
21 | it.forEach { item ->
22 | print(item)
23 | }
24 | println()
25 | }
26 | }
27 | }
28 |
29 | // 输入:nums = [1,2,3]
30 | // 输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
31 | fun subsets(nums: IntArray): List> {
32 | val result = ArrayList>()
33 | backtracking(nums, 0, arrayListOf(), result)
34 | return result
35 | }
36 |
37 | private fun backtracking(nums: IntArray, index: Int, subList: ArrayList, result: ArrayList>) {
38 | if (index == nums.size) {
39 | result.add(ArrayList(subList))
40 | return
41 | }
42 |
43 | backtracking(nums, index + 1, subList, result)
44 |
45 | subList.add(nums[index])
46 | backtracking(nums, index + 1, subList, result)
47 | subList.removeAt(subList.size - 1)
48 | }
49 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/medium/SwapPairs.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.medium
2 |
3 | import com.daily.algothrim.leetcode.ListNode
4 |
5 | /**
6 | * 24. 两两交换链表中的节点
7 | */
8 | class SwapPairs {
9 |
10 | companion object {
11 | @JvmStatic
12 | fun main(args: Array) {
13 | SwapPairs().swapPairs(
14 | ListNode(1).apply {
15 | next = ListNode(2).apply {
16 | next = ListNode(3).apply {
17 | next = ListNode(4)
18 | }
19 | }
20 | }
21 | )?.printAll()
22 | }
23 | }
24 |
25 | fun swapPairs(head: ListNode?): ListNode? {
26 | val guardNode = ListNode(-1)
27 | guardNode.next = head
28 | var temp: ListNode? = guardNode
29 |
30 | while (temp?.next?.next != null) {
31 | val firstNode = temp.next
32 | val secondNode = temp.next?.next
33 |
34 | temp.next = secondNode
35 | firstNode?.next = secondNode?.next
36 | secondNode?.next = firstNode
37 |
38 | temp = firstNode
39 | }
40 |
41 | return guardNode.next
42 | }
43 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/medium/ThreeSumClosest.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.medium
2 |
3 | /**
4 | * 16. 最接近的三数之和
5 | */
6 | class ThreeSumClosest {
7 |
8 | companion object {
9 |
10 | @JvmStatic
11 | fun main(args: Array) {
12 | println(ThreeSumClosest().threeSumClosest(intArrayOf(-1, 2, 1, -4), 1))
13 | println(ThreeSumClosest().threeSumClosest(intArrayOf(0, 0, 0), 1))
14 | }
15 | }
16 |
17 | fun threeSumClosest(nums: IntArray, target: Int): Int {
18 | nums.sort()
19 | val size = nums.size
20 | var bestResult = Int.MAX_VALUE
21 |
22 | for (i in 0 until size) {
23 | if (i > 0 && nums[i] == nums[i - 1]) continue
24 |
25 | var j = i + 1
26 | var k = size - 1
27 | while (j < k) {
28 | val sum = nums[i] + nums[j] + nums[k]
29 | if (sum == target) return target
30 |
31 | if (Math.abs(sum - target) < Math.abs(bestResult - target)) {
32 | bestResult = sum
33 | }
34 |
35 | if (sum > target) {
36 | k--
37 | while (j < k && nums[k] == nums[k + 1]) {
38 | k--
39 | }
40 | } else {
41 | j++
42 | while (j < k && nums[j] == nums[j - 1]) {
43 | j++
44 | }
45 | }
46 | }
47 | }
48 | return bestResult
49 | }
50 |
51 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/medium/UniquePaths.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.medium
2 |
3 | /**
4 | * 62. 不同路径
5 | *
6 | * 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。
7 | *
8 | * 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。
9 | * 问总共有多少条不同的路径?
10 | */
11 | class UniquePaths {
12 |
13 | companion object {
14 | @JvmStatic
15 | fun main(args: Array) {
16 | println(UniquePaths().uniquePaths(3, 7))
17 | println(UniquePaths().uniquePaths(3, 2))
18 | println(UniquePaths().uniquePaths(7, 3))
19 | println(UniquePaths().uniquePaths(3, 3))
20 | }
21 | }
22 |
23 | // 输入:m = 3, n = 7
24 | // 输出:28
25 | fun uniquePaths(m: Int, n: Int): Int {
26 | val path = Array(m) { IntArray(n) }
27 | path[0][0] = 1
28 | for (i in 0 until m) {
29 | for (j in 0 until n) {
30 | if (i == 0 && j == 0) continue
31 | if (i == 0 && j > 0) {
32 | path[i][j] = path[i][j - 1]
33 | } else if (i > 0 && j == 0) {
34 | path[i][j] = path[i - 1][j]
35 | } else {
36 | path[i][j] = path[i - 1][j] + path[i][j - 1]
37 | }
38 | }
39 | }
40 | return path[m - 1][n - 1]
41 | }
42 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/CanConstruct.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | /**
4 | * 383. 赎金信
5 | */
6 |
7 | /*
8 | 给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。
9 |
10 | 如果可以,返回 true ;否则返回 false 。
11 |
12 | magazine 中的每个字符只能在 ransomNote 中使用一次。
13 |
14 |
15 |
16 | 示例 1:
17 |
18 | 输入:ransomNote = "a", magazine = "b"
19 | 输出:false
20 | 示例 2:
21 |
22 | 输入:ransomNote = "aa", magazine = "ab"
23 | 输出:false
24 | 示例 3:
25 |
26 | 输入:ransomNote = "aa", magazine = "aab"
27 | 输出:true
28 |
29 |
30 | 提示:
31 |
32 | 1 <= ransomNote.length, magazine.length <= 105
33 | ransomNote 和 magazine 由小写英文字母组成
34 | */
35 | class CanConstruct {
36 |
37 | companion object {
38 | @JvmStatic
39 | fun main(args: Array) {
40 | println(CanConstruct().canConstruct("a", "b"))
41 | println(CanConstruct().canConstruct("aa", "ab"))
42 | println(CanConstruct().canConstruct("aa", "aab"))
43 | }
44 | }
45 |
46 | fun canConstruct(ransomNote: String, magazine: String): Boolean {
47 | val map = hashMapOf()
48 | for (item in ransomNote) {
49 | map[item] = map.getOrDefault(item, 0) + 1
50 | }
51 |
52 | for (item in magazine) {
53 | if (map[item] != null) {
54 | map[item] = map.getOrDefault(item, 0) - 1
55 | if (map[item] == 0) {
56 | map.remove(item)
57 | if (map.size == 0) return true
58 | }
59 | }
60 | }
61 |
62 | return false
63 | }
64 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/CanJump.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | import kotlin.math.max
4 |
5 | /**
6 | * 55. 跳跃游戏
7 | */
8 |
9 | /*
10 | 给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。
11 |
12 | 判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。
13 |
14 |
15 |
16 | 示例 1:
17 |
18 | 输入:nums = [2,3,1,1,4]
19 | 输出:true
20 | 解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。
21 | 示例 2:
22 |
23 | 输入:nums = [3,2,1,0,4]
24 | 输出:false
25 | 解释:无论怎样,总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 , 所以永远不可能到达最后一个下标。
26 |
27 |
28 | 提示:
29 |
30 | 1 <= nums.length <= 104
31 | 0 <= nums[i] <= 105
32 | */
33 | class CanJump {
34 | companion object {
35 | @JvmStatic
36 | fun main(args: Array) {
37 | println(CanJump().canJump(intArrayOf(2, 3, 1, 1, 4)))
38 | println(CanJump().canJump(intArrayOf(3, 2, 1, 0, 4)))
39 | println(CanJump().canJump(intArrayOf(1, 13, 1, 1, 4)))
40 | }
41 | }
42 |
43 | fun canJump(nums: IntArray): Boolean {
44 | var k = 0
45 | for (i in nums.indices) {
46 | if (i > k) return false
47 | k = max(k, i + nums[i])
48 | }
49 | return true
50 | }
51 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/Candy.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | import kotlin.math.max
4 |
5 | /**
6 | * 135. 分发糖果
7 | */
8 |
9 | /*
10 | n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。
11 |
12 | 你需要按照以下要求,给这些孩子分发糖果:
13 |
14 | 每个孩子至少分配到 1 个糖果。
15 | 相邻两个孩子评分更高的孩子会获得更多的糖果。
16 | 请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。
17 |
18 |
19 |
20 | 示例 1:
21 |
22 | 输入:ratings = [1,0,2]
23 | 输出:5
24 | 解释:你可以分别给第一个、第二个、第三个孩子分发 2、1、2 颗糖果。
25 | 示例 2:
26 |
27 | 输入:ratings = [1,2,2]
28 | 输出:4
29 | 解释:你可以分别给第一个、第二个、第三个孩子分发 1、2、1 颗糖果。
30 | 第三个孩子只得到 1 颗糖果,这满足题面中的两个条件。
31 |
32 |
33 | 提示:
34 |
35 | n == ratings.length
36 | 1 <= n <= 2 * 104
37 | 0 <= ratings[i] <= 2 * 104
38 | */
39 | class Candy {
40 |
41 | companion object {
42 | @JvmStatic
43 | fun main(args: Array) {
44 | println(Candy().candy(intArrayOf(1,0,2)))
45 | println(Candy().candy(intArrayOf(1,2,2)))
46 | }
47 | }
48 |
49 | fun candy(ratings: IntArray): Int {
50 | val n = ratings.size
51 | val left = IntArray(n)
52 | var count = 0
53 | for (i in 0 until n) {
54 | if (i > 0 && ratings[i] > ratings[i - 1]) {
55 | left[i] = left[i - 1] + 1
56 | } else {
57 | left[i] = 1
58 | }
59 | }
60 |
61 | var r = 1
62 | for (j in n - 1 downTo 0) {
63 | if (j < n - 1 && ratings[j] > ratings[j + 1]) {
64 | r++
65 | } else {
66 | r = 1
67 | }
68 | count += max(left[j], r)
69 | }
70 | return count
71 | }
72 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/CheckInclusion.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | /**
4 | * 567. 字符串的排列
5 | */
6 |
7 | /*
8 | 给你两个字符串 s1 和 s2 ,写一个函数来判断 s2 是否包含 s1 的排列。如果是,返回 true ;否则,返回 false 。
9 |
10 | 换句话说,s1 的排列之一是 s2 的 子串 。
11 |
12 |
13 |
14 | 示例 1:
15 |
16 | 输入:s1 = "ab" s2 = "eidbaooo"
17 | 输出:true
18 | 解释:s2 包含 s1 的排列之一 ("ba").
19 | 示例 2:
20 |
21 | 输入:s1= "ab" s2 = "eidboaoo"
22 | 输出:false
23 |
24 |
25 | 提示:
26 |
27 | 1 <= s1.length, s2.length <= 104
28 | s1 和 s2 仅包含小写字母
29 | */
30 | class CheckInclusion {
31 |
32 | companion object {
33 | @JvmStatic
34 | fun main(args: Array) {
35 | println(CheckInclusion().checkInclusion("ab", "eidbaooo"))
36 | }
37 | }
38 |
39 | /**
40 | * O(n + m + 字母集)
41 | * O(字母集)
42 | */
43 | fun checkInclusion(s1: String, s2: String): Boolean {
44 | val n = s1.length
45 | val m = s2.length
46 | if (n > m) return false
47 | val ct1 = IntArray(26)
48 | val ct2 = IntArray(26)
49 | for (i in 0 until n) {
50 | ct1[s1[i] - 'a']++
51 | ct2[s2[i] - 'a']++
52 | }
53 | if (ct1.contentEquals(ct2)) {
54 | return true
55 | }
56 |
57 | for (j in n until m) {
58 | ct2[s2[j] - 'a']++
59 | ct2[s2[j - n] - 'a']--
60 | if (ct1.contentEquals(ct2)) return true
61 | }
62 | return false
63 | }
64 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/ClimbStairs.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | /**
4 | * 70. 爬楼梯
5 | */
6 |
7 | /*
8 | 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
9 |
10 | 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
11 |
12 | 示例 1:
13 |
14 | 输入:n = 2
15 | 输出:2
16 | 解释:有两种方法可以爬到楼顶。
17 | 1. 1 阶 + 1 阶
18 | 2. 2 阶
19 | 示例 2:
20 |
21 | 输入:n = 3
22 | 输出:3
23 | 解释:有三种方法可以爬到楼顶。
24 | 1. 1 阶 + 1 阶 + 1 阶
25 | 2. 1 阶 + 2 阶
26 | 3. 2 阶 + 1 阶
27 |
28 | 提示:
29 |
30 | 1 <= n <= 45
31 | */
32 | class ClimbStairs {
33 |
34 | companion object {
35 | @JvmStatic
36 | fun main(args: Array) {
37 | println(ClimbStairs().climbStairs(2))
38 | println(ClimbStairs().climbStairs(3))
39 | }
40 | }
41 |
42 | /**
43 | * O(n)
44 | * O(n)
45 | */
46 | fun climbStairs(n: Int): Int {
47 | if (n == 1) return 1
48 | if (n == 2) return 2
49 | val dp = IntArray(n + 1)
50 | dp[1] = 1
51 | dp[2] = 2
52 | for (i in 3..n) {
53 | dp[i] = dp[i - 1] + dp[i - 2]
54 | }
55 | return dp[n]
56 | }
57 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/Convert.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | import java.lang.StringBuilder
4 |
5 | /**
6 | * 6. Z 字形变换
7 | */
8 |
9 | /*
10 | 将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
11 |
12 | 比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:
13 |
14 | P A H N
15 | A P L S I I G
16 | Y I R
17 | 之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"。
18 |
19 | 请你实现这个将字符串进行指定行数变换的函数:
20 |
21 | string convert(string s, int numRows);
22 |
23 |
24 | 示例 1:
25 |
26 | 输入:s = "PAYPALISHIRING", numRows = 3
27 | 输出:"PAHNAPLSIIGYIR"
28 | 示例 2:
29 | 输入:s = "PAYPALISHIRING", numRows = 4
30 | 输出:"PINALSIGYAHRPI"
31 | 解释:
32 | P I N
33 | A L S I G
34 | Y A H R
35 | P I
36 | 示例 3:
37 |
38 | 输入:s = "A", numRows = 1
39 | 输出:"A"
40 |
41 |
42 | 提示:
43 |
44 | 1 <= s.length <= 1000
45 | s 由英文字母(小写和大写)、',' 和 '.' 组成
46 | 1 <= numRows <= 1000
47 | */
48 | class Convert {
49 |
50 | companion object {
51 |
52 | @JvmStatic
53 | fun main(args: Array) {
54 | println(Convert().convert("PAYPALISHIRING", 3))
55 | println(Convert().convert("PAYPALISHIRING", 4))
56 | println(Convert().convert("A", 1))
57 | }
58 | }
59 |
60 | fun convert(s: String, numRows: Int): String {
61 | if (numRows < 2) return s
62 | val result = StringBuilder()
63 | val rowsArray = Array(numRows) { StringBuilder() }
64 | var flag = -1
65 | var i = 0
66 | for (item in s) {
67 | if (i == 0 || i == numRows - 1) flag = -flag
68 | rowsArray[i].append(item)
69 | i += flag
70 | }
71 | for (item in rowsArray) {
72 | result.append(item)
73 | }
74 | return result.toString()
75 | }
76 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/CountNodes.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | import com.daily.algothrim.leetcode.TreeNode
4 |
5 | /**
6 | * 222. 完全二叉树的节点个数
7 | */
8 |
9 | /*
10 | 给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。
11 |
12 | 完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。
13 |
14 | 示例 1:
15 |
16 | 输入:root = [1,2,3,4,5,6]
17 | 输出:6
18 | 示例 2:
19 |
20 | 输入:root = []
21 | 输出:0
22 | 示例 3:
23 |
24 | 输入:root = [1]
25 | 输出:1
26 |
27 | 提示:
28 |
29 | 树中节点的数目范围是[0, 5 * 104]
30 | 0 <= Node.val <= 5 * 104
31 | 题目数据保证输入的树是 完全二叉树
32 |
33 | 进阶:遍历树来统计节点是一种时间复杂度为 O(n) 的简单解决方案。你可以设计一个更快的算法吗?
34 | */
35 | class CountNodes {
36 |
37 | companion object {
38 | @JvmStatic
39 | fun main(args: Array) {
40 | println(CountNodes().countNodes(TreeNode(1).apply {
41 | left = TreeNode(2).apply {
42 | left = TreeNode(4)
43 | right = TreeNode(5)
44 | }
45 | right = TreeNode(3).apply {
46 | left = TreeNode(6)
47 | }
48 | }))
49 | }
50 | }
51 |
52 | private var count = 0
53 |
54 | /**
55 | * O(n)
56 | * O(n)
57 | */
58 | fun countNodes(root: TreeNode?): Int {
59 | dfs(root)
60 | return count
61 | }
62 |
63 | private fun dfs(root: TreeNode?) {
64 | if (root == null) return
65 | count++
66 | countNodes(root.left)
67 | countNodes(root.right)
68 | }
69 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/FindKthLargest.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | /**
4 | * 215. 数组中的第K个最大元素
5 | */
6 | /*
7 | 给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。
8 |
9 | 请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
10 |
11 | 你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。
12 |
13 |
14 |
15 | 示例 1:
16 |
17 | 输入: [3,2,1,5,6,4], k = 2
18 | 输出: 5
19 | 示例 2:
20 |
21 | 输入: [3,2,3,1,2,4,5,5,6], k = 4
22 | 输出: 4
23 |
24 |
25 | 提示:
26 |
27 | 1 <= k <= nums.length <= 105
28 | -104 <= nums[i] <= 104
29 | */
30 | class FindKthLargest {
31 |
32 | companion object {
33 | @JvmStatic
34 | fun main(args: Array) {
35 | println(FindKthLargest().findKthLargest(intArrayOf(3, 2, 1, 5, 6, 4), 2))
36 | println(FindKthLargest().findKthLargest(intArrayOf(3, 2, 3, 1, 2, 4, 5, 5, 6), 4))
37 | }
38 | }
39 |
40 | /**
41 | * O(n)
42 | * O(logn)
43 | */
44 | fun findKthLargest(nums: IntArray, k: Int): Int {
45 | return quickSort(nums, 0, nums.size - 1, nums.size - k)
46 | }
47 |
48 | private fun quickSort(nums: IntArray, l: Int, r: Int, k: Int): Int {
49 | if (l == r) return nums[k]
50 | var i = l - 1
51 | var j = r + 1
52 | val x = nums[l]
53 |
54 | while (i < j) {
55 | do {
56 | i++
57 | } while (nums[i] < x)
58 | do {
59 | j--
60 | } while (nums[j] > x)
61 | if (i < j) {
62 | val temp = nums[i]
63 | nums[i] = nums[j]
64 | nums[j] = temp
65 | }
66 | }
67 | return if (k <= j) quickSort(nums, l, j, k) else quickSort(nums, j + 1, r, k)
68 | }
69 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/GetMinimumDifference.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | import com.daily.algothrim.leetcode.TreeNode
4 | import kotlin.math.min
5 |
6 | /**
7 | * 530. 二叉搜索树的最小绝对差
8 | */
9 |
10 | /*
11 | 给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。
12 |
13 | 差值是一个正数,其数值等于两值之差的绝对值。
14 |
15 |
16 |
17 | 示例 1:
18 |
19 |
20 | 输入:root = [4,2,6,1,3]
21 | 输出:1
22 | 示例 2:
23 |
24 |
25 | 输入:root = [1,0,48,null,null,12,49]
26 | 输出:1
27 |
28 |
29 | 提示:
30 |
31 | 树中节点的数目范围是 [2, 104]
32 | 0 <= Node.val <= 105
33 | */
34 | class GetMinimumDifference {
35 |
36 | companion object {
37 | @JvmStatic
38 | fun main(args: Array) {
39 | println(GetMinimumDifference().getMinimumDifference(TreeNode(4).apply {
40 | left = TreeNode(2).apply {
41 | left = TreeNode(1)
42 | right = TreeNode(3)
43 | }
44 | right = TreeNode(6)
45 | }))
46 | }
47 | }
48 |
49 | private var minResult = Int.MAX_VALUE
50 | private var pre = -1
51 |
52 | fun getMinimumDifference(root: TreeNode?): Int {
53 | inOrderTraversal(root)
54 | return minResult
55 | }
56 |
57 | /**
58 | * O(n)
59 | * O(n)
60 | */
61 | private fun inOrderTraversal(root: TreeNode?) {
62 | if (root == null) return
63 | inOrderTraversal(root.left)
64 | if (pre == -1) {
65 | pre = root.`val`
66 | } else {
67 | minResult = min(minResult, root.`val` - pre)
68 | pre = root.`val`
69 | }
70 | inOrderTraversal(root.right)
71 | }
72 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/HIndex.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | /**
4 | * 274. H 指数
5 | */
6 | /*
7 | 给你一个整数数组 citations ,其中 citations[i] 表示研究者的第 i 篇论文被引用的次数。计算并返回该研究者的 h 指数。
8 |
9 | 根据维基百科上 h 指数的定义:h 代表“高引用次数” ,一名科研人员的 h 指数 是指他(她)至少发表了 h 篇论文,并且 至少 有 h 篇论文被引用次数大于等于 h 。如果 h 有多种可能的值,h 指数 是其中最大的那个。
10 |
11 |
12 |
13 | 示例 1:
14 |
15 | 输入:citations = [3,0,6,1,5]
16 | 输出:3
17 | 解释:给定数组表示研究者总共有 5 篇论文,每篇论文相应的被引用了 3, 0, 6, 1, 5 次。
18 | 由于研究者有 3 篇论文每篇 至少 被引用了 3 次,其余两篇论文每篇被引用 不多于 3 次,所以她的 h 指数是 3。
19 | 示例 2:
20 |
21 | 输入:citations = [1,3,1]
22 | 输出:1
23 |
24 |
25 | 提示:
26 |
27 | n == citations.length
28 | 1 <= n <= 5000
29 | 0 <= citations[i] <= 1000
30 | */
31 | class HIndex {
32 |
33 | companion object {
34 | @JvmStatic
35 | fun main(args: Array) {
36 | println(HIndex().hIndex(intArrayOf(3, 0, 6, 1, 5)))
37 | println(HIndex().hIndex(intArrayOf(1, 3, 1)))
38 | }
39 | }
40 |
41 | // citations = [3,0,6,1,5]
42 | fun hIndex(citations: IntArray): Int {
43 | citations.sort()
44 | var i = citations.size - 1
45 | var h = 0
46 | while (i >= 0 && citations[i] > h) {
47 | h++
48 | i--
49 | }
50 | return h
51 | }
52 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/InvertTree.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | import com.daily.algothrim.leetcode.TreeNode
4 |
5 | /**
6 | * 226. 翻转二叉树
7 | */
8 |
9 | /*
10 | 给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。
11 |
12 | 示例 1:
13 |
14 | 输入:root = [4,2,7,1,3,6,9]
15 | 输出:[4,7,2,9,6,3,1]
16 | 示例 2:
17 |
18 | 输入:root = [2,1,3]
19 | 输出:[2,3,1]
20 | 示例 3:
21 |
22 | 输入:root = []
23 | 输出:[]
24 |
25 | 提示:
26 |
27 | 树中节点数目范围在 [0, 100] 内
28 | -100 <= Node.val <= 100
29 | */
30 | class InvertTree {
31 |
32 | companion object {
33 | @JvmStatic
34 | fun main(args: Array) {
35 |
36 | }
37 | }
38 |
39 | /**
40 | * O(n)
41 | * O(n)
42 | */
43 | fun invertTree(root: TreeNode?): TreeNode? {
44 | if (root == null) return null
45 | val left = invertTree(root.left)
46 | val right = invertTree(root.right)
47 | root.left = right
48 | root.right = left
49 | return root
50 | }
51 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/IsAnagram.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | /**
4 | * 242. 有效的字母异位词
5 | */
6 |
7 | /*
8 | 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
9 |
10 | 注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。
11 |
12 |
13 |
14 | 示例 1:
15 |
16 | 输入: s = "anagram", t = "nagaram"
17 | 输出: true
18 | 示例 2:
19 |
20 | 输入: s = "rat", t = "car"
21 | 输出: false
22 |
23 |
24 | 提示:
25 |
26 | 1 <= s.length, t.length <= 5 * 104
27 | s 和 t 仅包含小写字母
28 |
29 |
30 | 进阶: 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?
31 | */
32 | class IsAnagram {
33 |
34 | companion object {
35 | @JvmStatic
36 | fun main(args: Array) {
37 | println(IsAnagram().isAnagram("anagram", "nagaram"))
38 | println(IsAnagram().isAnagram("rat", "car"))
39 | }
40 | }
41 |
42 | fun isAnagram(s: String, t: String): Boolean {
43 | if (s.length != t.length) return false
44 | val map = hashMapOf()
45 | for (item in s) {
46 | map[item] = map.getOrDefault(item, 0) + 1
47 | }
48 | for (item in t) {
49 | if (!map.containsKey(item)) return false
50 | if (map.getOrDefault(item, 0) == 1) {
51 | map.remove(item)
52 | } else {
53 | map[item] = map.getOrDefault(item, 0) - 1
54 | }
55 | }
56 | return map.size == 0
57 | }
58 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/IsIsomorphic.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | /**
4 | * 205. 同构字符串
5 | */
6 |
7 | /*
8 | 给定两个字符串 s 和 t ,判断它们是否是同构的。
9 |
10 | 如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的。
11 |
12 | 每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,相同字符只能映射到同一个字符上,字符可以映射到自己本身。
13 |
14 |
15 |
16 | 示例 1:
17 |
18 | 输入:s = "egg", t = "add"
19 | 输出:true
20 | 示例 2:
21 |
22 | 输入:s = "foo", t = "bar"
23 | 输出:false
24 | 示例 3:
25 |
26 | 输入:s = "paper", t = "title"
27 | 输出:true
28 |
29 |
30 | 提示:
31 |
32 | 1 <= s.length <= 5 * 104
33 | t.length == s.length
34 | s 和 t 由任意有效的 ASCII 字符组成
35 | */
36 | class IsIsomorphic {
37 |
38 | companion object {
39 | @JvmStatic
40 | fun main(args: Array) {
41 | println(IsIsomorphic().isIsomorphic("egg", "add"))
42 | println(IsIsomorphic().isIsomorphic("foo", "bar"))
43 | println(IsIsomorphic().isIsomorphic("paper", "title"))
44 | println(IsIsomorphic().isIsomorphic("badc", "baba"))
45 | }
46 | }
47 |
48 | fun isIsomorphic(s: String, t: String): Boolean {
49 | val sMap = hashMapOf()
50 | val tMap = hashMapOf()
51 |
52 | for (i in s.indices) {
53 | if (sMap.containsKey(s[i]) && sMap[s[i]] != t[i] || tMap.containsKey(t[i]) && tMap[t[i]] != s[i]) return false
54 | sMap[s[i]] = t[i]
55 | tMap[t[i]] = s[i]
56 | }
57 |
58 | return true
59 | }
60 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/IsPalindrome.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | /**
4 | * 125. 验证回文串
5 | */
6 |
7 | /*
8 | 如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。
9 |
10 | 字母和数字都属于字母数字字符。
11 |
12 | 给你一个字符串 s,如果它是 回文串 ,返回 true ;否则,返回 false 。
13 |
14 |
15 |
16 | 示例 1:
17 |
18 | 输入: s = "A man, a plan, a canal: Panama"
19 | 输出:true
20 | 解释:"amanaplanacanalpanama" 是回文串。
21 | 示例 2:
22 |
23 | 输入:s = "race a car"
24 | 输出:false
25 | 解释:"raceacar" 不是回文串。
26 | 示例 3:
27 |
28 | 输入:s = " "
29 | 输出:true
30 | 解释:在移除非字母数字字符之后,s 是一个空字符串 "" 。
31 | 由于空字符串正着反着读都一样,所以是回文串。
32 |
33 |
34 | 提示:
35 |
36 | 1 <= s.length <= 2 * 105
37 | s 仅由可打印的 ASCII 字符组成
38 | */
39 | class IsPalindrome {
40 |
41 | companion object {
42 | @JvmStatic
43 | fun main(args: Array) {
44 | println(IsPalindrome().isPalindrome("A man, a plan, a canal: Panama"))
45 | println(IsPalindrome().isPalindrome("race a car"))
46 | println(IsPalindrome().isPalindrome(" "))
47 | println(IsPalindrome().isPalindrome("0P"))
48 | }
49 | }
50 |
51 | fun isPalindrome(s: String): Boolean {
52 | val temp = s.lowercase()
53 | var start = 0
54 | var end = temp.length - 1
55 |
56 | while (start < end) {
57 | if (!temp[start].isLetterOrDigit()) {
58 | start++
59 | continue
60 | }
61 | if (!temp[end].isLetterOrDigit()) {
62 | end--
63 | continue
64 | }
65 |
66 | if (temp[start++] != temp[end--]) return false
67 | }
68 | return true
69 | }
70 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/IsPalindromeInt.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | /**
4 | * 9. 回文数
5 | */
6 |
7 | /*
8 | 给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
9 |
10 | 回文数
11 | 是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
12 |
13 | 例如,121 是回文,而 123 不是。
14 |
15 |
16 | 示例 1:
17 |
18 | 输入:x = 121
19 | 输出:true
20 | 示例 2:
21 |
22 | 输入:x = -121
23 | 输出:false
24 | 解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
25 | 示例 3:
26 |
27 | 输入:x = 10
28 | 输出:false
29 | 解释:从右向左读, 为 01 。因此它不是一个回文数。
30 |
31 | 提示:
32 |
33 | -231 <= x <= 231 - 1
34 |
35 | 进阶:你能不将整数转为字符串来解决这个问题吗?
36 | */
37 | class IsPalindromeInt {
38 |
39 | companion object {
40 | @JvmStatic
41 | fun main(args: Array) {
42 | println(IsPalindromeInt().isPalindrome(121))
43 | println(IsPalindromeInt().isPalindrome(-121))
44 | println(IsPalindromeInt().isPalindrome(10))
45 | }
46 | }
47 |
48 | /**
49 | * O(logn)
50 | * O(1)
51 | */
52 | fun isPalindrome(x: Int): Boolean {
53 | if (x < 0 || (x % 10 == 0 && x != 0)) return false
54 |
55 | var reverseInt = 0
56 | var temp = x
57 |
58 | while (temp > reverseInt) {
59 | reverseInt = reverseInt * 10 + temp % 10
60 | temp /= 10
61 | }
62 |
63 | return temp == reverseInt || temp == reverseInt / 10
64 | }
65 |
66 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/IsSameTree.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | import com.daily.algothrim.leetcode.TreeNode
4 |
5 | /**
6 | * 100. 相同的树
7 | */
8 |
9 | /*
10 | 给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。
11 |
12 | 如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
13 |
14 | 示例 1:
15 |
16 | 输入:p = [1,2,3], q = [1,2,3]
17 | 输出:true
18 | 示例 2:
19 |
20 |
21 | 输入:p = [1,2], q = [1,null,2]
22 | 输出:false
23 | 示例 3:
24 |
25 |
26 | 输入:p = [1,2,1], q = [1,1,2]
27 | 输出:false
28 |
29 |
30 | 提示:
31 |
32 | 两棵树上的节点数目都在范围 [0, 100] 内
33 | -104 <= Node.val <= 104
34 | */
35 |
36 | class IsSameTree {
37 |
38 | companion object {
39 | @JvmStatic
40 | fun main(args: Array) {
41 | println(IsSameTree().isSameTree(TreeNode(1).apply {
42 | left = TreeNode(2)
43 | right = TreeNode(3)
44 | }, TreeNode(1).apply {
45 | left = TreeNode(2)
46 | right = TreeNode(3)
47 | }))
48 | println(IsSameTree().isSameTree(TreeNode(1).apply {
49 | left = TreeNode(2)
50 | }, TreeNode(1).apply {
51 | right = TreeNode(2)
52 | }))
53 | }
54 | }
55 |
56 | /**
57 | * O(min(n, m)) n,m二叉树节点数
58 | * O(min(n, m)) 不会超过最小二叉树的高度,最坏情况下高度等于节点数
59 | */
60 | fun isSameTree(p: TreeNode?, q: TreeNode?): Boolean {
61 | if (p == null && q == null) return true
62 | if (p == null || q == null) return false
63 | if (p.`val` != q.`val`) return false
64 | return isSameTree(p.left, q.left) && isSameTree(p.right, q.right)
65 | }
66 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/IsSubsequence.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | /**
4 | * 392. 判断子序列
5 | */
6 |
7 | /*
8 | 给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
9 |
10 | 字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。
11 |
12 | 进阶:
13 |
14 | 如果有大量输入的 S,称作 S1, S2, ... , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码?
15 |
16 | 致谢:
17 |
18 | 特别感谢 @pbrother 添加此问题并且创建所有测试用例。
19 |
20 |
21 |
22 | 示例 1:
23 |
24 | 输入:s = "abc", t = "ahbgdc"
25 | 输出:true
26 | 示例 2:
27 |
28 | 输入:s = "axc", t = "ahbgdc"
29 | 输出:false
30 |
31 |
32 | 提示:
33 |
34 | 0 <= s.length <= 100
35 | 0 <= t.length <= 10^4
36 | 两个字符串都只由小写字符组成。
37 | */
38 | class IsSubsequence {
39 |
40 | companion object {
41 | @JvmStatic
42 | fun main(args: Array) {
43 | println(IsSubsequence().isSubsequence("abc", "ahbgdc"))
44 | println(IsSubsequence().isSubsequence("axc", "ahbgdc"))
45 | println(IsSubsequence().isSubsequence("", "ahbgdc"))
46 | }
47 | }
48 |
49 | fun isSubsequence(s: String, t: String): Boolean {
50 | val sSize = s.length
51 | val tSize = t.length
52 | if (sSize > tSize) return false
53 | if (sSize == 0) return true
54 |
55 | var i = 0
56 | var j = 0
57 | while (i < tSize && j < sSize) {
58 | if (t[i] == s[j]) {
59 | j++
60 | }
61 | i++
62 | }
63 | return j == sSize
64 | }
65 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/IsValid.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | import java.util.Stack
4 |
5 | /**
6 | * 20. 有效的括号
7 | */
8 |
9 | /*
10 | 给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。
11 |
12 | 有效字符串需满足:
13 |
14 | 左括号必须用相同类型的右括号闭合。
15 | 左括号必须以正确的顺序闭合。
16 | 每个右括号都有一个对应的相同类型的左括号。
17 |
18 |
19 | 示例 1:
20 |
21 | 输入:s = "()"
22 | 输出:true
23 | 示例 2:
24 |
25 | 输入:s = "()[]{}"
26 | 输出:true
27 | 示例 3:
28 |
29 | 输入:s = "(]"
30 | 输出:false
31 |
32 |
33 | 提示:
34 |
35 | 1 <= s.length <= 104
36 | s 仅由括号 '()[]{}' 组成
37 | */
38 | class IsValid {
39 |
40 | companion object {
41 | @JvmStatic
42 | fun main(args: Array) {
43 | println(IsValid().isValid("()"))
44 | println(IsValid().isValid("()[]{}"))
45 | println(IsValid().isValid("(]"))
46 | println(IsValid().isValid("(())"))
47 | }
48 | }
49 |
50 | fun isValid(s: String): Boolean {
51 | val stack = Stack()
52 |
53 | for (item in s) {
54 | if (item == '(' || item == '{' || item == '[') {
55 | stack.push(item)
56 | } else if (stack.empty() || (item == ')' && stack.peek() != '('
57 | || item == '}' && stack.peek() != '{'
58 | || item == ']' && stack.peek() != '[')
59 | ) {
60 | return false
61 | } else {
62 | stack.pop()
63 | }
64 | }
65 | return stack.isEmpty()
66 | }
67 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/Jump.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | /**
4 | * 45. 跳跃游戏 II
5 | */
6 |
7 | /*
8 | 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。
9 |
10 | 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums[i + j] 处:
11 |
12 | 0 <= j <= nums[i]
13 | i + j < n
14 | 返回到达 nums[n - 1] 的最小跳跃次数。生成的测试用例可以到达 nums[n - 1]。
15 |
16 |
17 |
18 | 示例 1:
19 |
20 | 输入: nums = [2,3,1,1,4]
21 | 输出: 2
22 | 解释: 跳到最后一个位置的最小跳跃数是 2。
23 | 从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。
24 | 示例 2:
25 |
26 | 输入: nums = [2,3,0,1,4]
27 | 输出: 2
28 |
29 |
30 | 提示:
31 |
32 | 1 <= nums.length <= 104
33 | 0 <= nums[i] <= 1000
34 | 题目保证可以到达 nums[n-1]
35 | */
36 | import kotlin.math.max
37 |
38 | class Jump {
39 |
40 | companion object {
41 | @JvmStatic
42 | fun main(args: Array) {
43 | println(Jump().jump(intArrayOf(2, 3, 1, 1, 4)))
44 | println(Jump().jump(intArrayOf(2, 3, 0, 1, 4)))
45 | }
46 | }
47 |
48 | fun jump(nums: IntArray): Int {
49 | var step = 0
50 | var maxPosition = 0
51 | var end = 0
52 | for (i in 0 until nums.size - 1) {
53 | maxPosition = max(maxPosition, i + nums[i])
54 | if (i == end) {
55 | end = maxPosition
56 | step++
57 | }
58 | }
59 | return step
60 | }
61 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/LargestNumber.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | /**
4 | * 179. 最大数
5 | */
6 |
7 | /*
8 | 给定一组非负整数 nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。
9 |
10 | 注意:输出结果可能非常大,所以你需要返回一个字符串而不是整数。
11 |
12 |
13 |
14 | 示例 1:
15 |
16 | 输入:nums = [10,2]
17 | 输出:"210"
18 | 示例 2:
19 |
20 | 输入:nums = [3,30,34,5,9]
21 | 输出:"9534330"
22 |
23 |
24 | 提示:
25 |
26 | 1 <= nums.length <= 100
27 | 0 <= nums[i] <= 109
28 | */
29 |
30 | class LargestNumber {
31 |
32 | companion object {
33 | @JvmStatic
34 | fun main(args: Array) {
35 | println(LargestNumber().largestNumber(intArrayOf(10, 2)))
36 | println(LargestNumber().largestNumber(intArrayOf(3, 30, 34, 5, 9)))
37 | println(LargestNumber().largestNumber(intArrayOf(1000000000, 1000000000)))
38 | }
39 | }
40 |
41 | /**
42 | * O(nlognlogm) n 序列长度,m32位整数最大值
43 | * O(logn)
44 | */
45 | fun largestNumber(nums: IntArray): String {
46 | if (nums.isEmpty()) return ""
47 | val list = nums.sortedWith { x, y ->
48 | (y.toString() + x.toString()).compareTo((x.toString() + y.toString()))
49 | }
50 | if (list[0] == 0) return "0"
51 | return StringBuilder().apply {
52 | list.forEach {
53 | append(it)
54 | }
55 | }.toString()
56 | }
57 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/LengthOfLastWord.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | /**
4 | * 58. 最后一个单词的长度
5 | */
6 |
7 | /*
8 | 给你一个字符串 s,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。
9 |
10 | 单词 是指仅由字母组成、不包含任何空格字符的最大
11 | 子字符串
12 | 。
13 |
14 |
15 |
16 | 示例 1:
17 |
18 | 输入:s = "Hello World"
19 | 输出:5
20 | 解释:最后一个单词是“World”,长度为5。
21 | 示例 2:
22 |
23 | 输入:s = " fly me to the moon "
24 | 输出:4
25 | 解释:最后一个单词是“moon”,长度为4。
26 | 示例 3:
27 |
28 | 输入:s = "luffy is still joyboy"
29 | 输出:6
30 | 解释:最后一个单词是长度为6的“joyboy”。
31 |
32 |
33 | 提示:
34 |
35 | 1 <= s.length <= 104
36 | s 仅有英文字母和空格 ' ' 组成
37 | s 中至少存在一个单词
38 | */
39 | class LengthOfLastWord {
40 |
41 | companion object {
42 | @JvmStatic
43 | fun main(args: Array) {
44 | println(LengthOfLastWord().lengthOfLastWord("Hello World"))
45 | println(LengthOfLastWord().lengthOfLastWord(" fly me to the moon "))
46 | println(LengthOfLastWord().lengthOfLastWord("luffy is still joyboy"))
47 | }
48 | }
49 |
50 | fun lengthOfLastWord(s: String): Int {
51 | var end = s.length - 1
52 | while (end >= 0 && s[end] == ' ') end--
53 | if (end < 0) return 0
54 | var start = end
55 | while (start >= 0 && s[start] != ' ') start--
56 | return end - start
57 | }
58 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/LongestCommonPrefix.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | import kotlin.math.min
4 |
5 | /**
6 | * 14. 最长公共前缀
7 | */
8 |
9 | /*
10 | 编写一个函数来查找字符串数组中的最长公共前缀。
11 |
12 | 如果不存在公共前缀,返回空字符串 ""。
13 |
14 |
15 |
16 | 示例 1:
17 |
18 | 输入:strs = ["flower","flow","flight"]
19 | 输出:"fl"
20 | 示例 2:
21 |
22 | 输入:strs = ["dog","racecar","car"]
23 | 输出:""
24 | 解释:输入不存在公共前缀。
25 |
26 |
27 | 提示:
28 |
29 | 1 <= strs.length <= 200
30 | 0 <= strs[i].length <= 200
31 | strs[i] 仅由小写英文字母组成
32 | */
33 | class LongestCommonPrefix {
34 |
35 | companion object {
36 | @JvmStatic
37 | fun main(args: Array) {
38 | println(LongestCommonPrefix().longestCommonPrefix(arrayOf("flower","flow","flight")))
39 | println(LongestCommonPrefix().longestCommonPrefix(arrayOf("dog","racecar","car")))
40 | }
41 | }
42 |
43 | fun longestCommonPrefix(strs: Array): String {
44 | var result = strs[0]
45 | for (i in 1 until strs.size) {
46 | val minLength = min(result.length, strs[i].length)
47 | var j = 0
48 | while (j < minLength) {
49 | if (result[j] != strs[i][j]) break
50 | j++
51 | }
52 | result = result.substring(0, j)
53 | if (result.isEmpty()) break
54 | }
55 | return result
56 | }
57 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/LongestConsecutive.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | import kotlin.math.max
4 |
5 | /**
6 | * 128. 最长连续序列
7 | */
8 |
9 | /*
10 | 给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
11 |
12 | 请你设计并实现时间复杂度为 O(n) 的算法解决此问题。
13 |
14 |
15 |
16 | 示例 1:
17 |
18 | 输入:nums = [100,4,200,1,3,2]
19 | 输出:4
20 | 解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。
21 | 示例 2:
22 |
23 | 输入:nums = [0,3,7,2,5,8,4,6,0,1]
24 | 输出:9
25 |
26 |
27 | 提示:
28 |
29 | 0 <= nums.length <= 105
30 | -109 <= nums[i] <= 109
31 | */
32 |
33 | class LongestConsecutive {
34 |
35 | companion object {
36 | @JvmStatic
37 | fun main(args: Array) {
38 | println(LongestConsecutive().longestConsecutive(intArrayOf(100, 4, 200, 1, 3, 2)))
39 | println(LongestConsecutive().longestConsecutive(intArrayOf(0, 3, 7, 2, 5, 8, 4, 6, 0, 1)))
40 | }
41 | }
42 |
43 | fun longestConsecutive(nums: IntArray): Int {
44 | val set = hashSetOf()
45 | for (item in nums) {
46 | set.add(item)
47 | }
48 |
49 | var maxLength = 0
50 | for (item in set) {
51 | if (!set.contains(item - 1)) {
52 | var curr = item
53 | var count = 1
54 | while (set.contains(curr + 1)) {
55 | count++
56 | curr++
57 | }
58 | maxLength = max(maxLength, count)
59 | }
60 | }
61 | return maxLength
62 | }
63 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/MaxArea.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | import kotlin.math.max
4 | import kotlin.math.min
5 |
6 | /**
7 | * 11. 盛最多水的容器
8 | */
9 |
10 | /*
11 | 给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
12 |
13 | 找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
14 |
15 | 返回容器可以储存的最大水量。
16 |
17 | 说明:你不能倾斜容器。
18 |
19 | 输入:[1,8,6,2,5,4,8,3,7]
20 | 输出:49
21 | 解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
22 | 示例 2:
23 |
24 | 输入:height = [1,1]
25 | 输出:1
26 |
27 |
28 | 提示:
29 |
30 | n == height.length
31 | 2 <= n <= 105
32 | 0 <= height[i] <= 104
33 | */
34 | class MaxArea {
35 |
36 | companion object {
37 | @JvmStatic
38 | fun main(args: Array) {
39 | println(MaxArea().maxArea(intArrayOf(1,8,6,2,5,4,8,3,7)))
40 | println(MaxArea().maxArea(intArrayOf(1, 1)))
41 | }
42 | }
43 |
44 | fun maxArea(height: IntArray): Int {
45 | val n = height.size
46 | var start = 0
47 | var end = n - 1
48 | var maxResult = 0
49 | while (start < end) {
50 | maxResult = max(min(height[start], height[end]) * (end - start), maxResult)
51 | if (height[start] > height[end]) {
52 | end--
53 | } else {
54 | start++
55 | }
56 | }
57 | return maxResult
58 | }
59 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/MaxDepth.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | import com.daily.algothrim.leetcode.TreeNode
4 | import kotlin.math.max
5 |
6 | /**
7 | * 104. 二叉树的最大深度
8 | */
9 |
10 | /*
11 | 给定一个二叉树 root ,返回其最大深度。
12 |
13 | 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。
14 |
15 | 示例 1:
16 |
17 | 输入:root = [3,9,20,null,null,15,7]
18 | 输出:3
19 | 示例 2:
20 |
21 | 输入:root = [1,null,2]
22 | 输出:2
23 |
24 | 提示:
25 |
26 | 树中节点的数量在 [0, 104] 区间内。
27 | -100 <= Node.val <= 100
28 | */
29 |
30 | class MaxDepth {
31 |
32 | companion object {
33 | @JvmStatic
34 | fun main(args: Array) {
35 | println(MaxDepth().maxDepth(
36 | TreeNode(3).apply {
37 | left = TreeNode(9)
38 | right = TreeNode(20).apply {
39 | left = TreeNode(15)
40 | right = TreeNode(7)
41 | }
42 | }
43 | ))
44 | println(MaxDepth().maxDepth(
45 | TreeNode(1).apply {
46 | right = TreeNode(2)
47 | }
48 | ))
49 | }
50 | }
51 |
52 | /**
53 | * O(n)
54 | * O(deep)
55 | */
56 | fun maxDepth(root: TreeNode?): Int {
57 | return deep(root, 0)
58 | }
59 |
60 | private fun deep(node: TreeNode?, currDeep: Int): Int {
61 | if (node == null) return currDeep
62 | val left = deep(node.left, currDeep + 1)
63 | val right = deep(node.right, currDeep + 1)
64 | return max(left, right)
65 | }
66 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/MaxProfit.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | import kotlin.math.max
4 |
5 | /**
6 | * 121. 买卖股票的最佳时机
7 | */
8 | /*
9 | 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。
10 |
11 | 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
12 |
13 | 返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。
14 |
15 |
16 |
17 | 示例 1:
18 |
19 | 输入:[7,1,5,3,6,4]
20 | 输出:5
21 | 解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
22 | 注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
23 | 示例 2:
24 |
25 | 输入:prices = [7,6,4,3,1]
26 | 输出:0
27 | 解释:在这种情况下, 没有交易完成, 所以最大利润为 0。
28 |
29 |
30 | 提示:
31 |
32 | 1 <= prices.length <= 105
33 | 0 <= prices[i] <= 104
34 | */
35 | class MaxProfit {
36 | companion object {
37 | @JvmStatic
38 | fun main(args: Array) {
39 | println(MaxProfit().maxProfit(intArrayOf(7, 1, 5, 3, 6, 4)))
40 | println(MaxProfit().maxProfit(intArrayOf(7, 6, 4, 3, 1)))
41 | println(MaxProfit().maxProfit(intArrayOf(7, 2, 9, 3, 1, 10)))
42 | }
43 | }
44 |
45 | fun maxProfit(prices: IntArray): Int {
46 | var max = 0
47 | var i = 1
48 | var temp = prices[0]
49 | val n = prices.size
50 | while (i < n) {
51 | if (prices[i] > temp) {
52 | max = max(max, prices[i] - temp)
53 | } else {
54 | temp = prices[i]
55 | }
56 | i++
57 | }
58 | return max
59 | }
60 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/MaxProfit2.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 |
4 | /**
5 | * 122. 买卖股票的最佳时机 II
6 | */
7 | /*
8 | 给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。
9 |
10 | 在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。
11 |
12 | 返回 你能获得的 最大 利润 。
13 |
14 |
15 |
16 | 示例 1:
17 |
18 | 输入:prices = [7,1,5,3,6,4]
19 | 输出:7
20 | 解释:在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。
21 | 随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6 - 3 = 3 。
22 | 总利润为 4 + 3 = 7 。
23 | 示例 2:
24 |
25 | 输入:prices = [1,2,3,4,5]
26 | 输出:4
27 | 解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。
28 | 总利润为 4 。
29 | 示例 3:
30 |
31 | 输入:prices = [7,6,4,3,1]
32 | 输出:0
33 | 解释:在这种情况下, 交易无法获得正利润,所以不参与交易可以获得最大利润,最大利润为 0 。
34 |
35 |
36 | 提示:
37 |
38 | 1 <= prices.length <= 3 * 104
39 | 0 <= prices[i] <= 104
40 | */
41 | class MaxProfit2 {
42 |
43 | companion object {
44 | @JvmStatic
45 | fun main(args: Array) {
46 | println(MaxProfit2().maxProfit(intArrayOf(7, 1, 5, 3, 6, 4)))
47 | println(MaxProfit2().maxProfit(intArrayOf(7, 6, 4, 3, 1)))
48 | println(MaxProfit2().maxProfit(intArrayOf(7, 2, 9, 3, 1, 10)))
49 | }
50 | }
51 |
52 | fun maxProfit(prices: IntArray): Int {
53 | var total = 0
54 | var temp = Int.MAX_VALUE
55 | for (item in prices) {
56 | if (item - temp > 0) {
57 | total += item - temp
58 | }
59 | temp = item
60 | }
61 | return total
62 | }
63 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/Merge.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | /**
4 | * 88. 合并两个有序数组
5 | */
6 | /*
7 | 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
8 |
9 | 请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
10 |
11 | 注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。
12 |
13 |
14 |
15 | 示例 1:
16 |
17 | 输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
18 | 输出:[1,2,2,3,5,6]
19 | 解释:需要合并 [1,2,3] 和 [2,5,6] 。
20 | 合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。
21 | 示例 2:
22 |
23 | 输入:nums1 = [1], m = 1, nums2 = [], n = 0
24 | 输出:[1]
25 | 解释:需要合并 [1] 和 [] 。
26 | 合并结果是 [1] 。
27 | 示例 3:
28 |
29 | 输入:nums1 = [0], m = 0, nums2 = [1], n = 1
30 | 输出:[1]
31 | 解释:需要合并的数组是 [] 和 [1] 。
32 | 合并结果是 [1] 。
33 | 注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。
34 | */
35 | class Merge {
36 |
37 | companion object {
38 | @JvmStatic
39 | fun main(args: Array) {
40 | val nums1 = intArrayOf(1, 2, 3, 0, 0, 0)
41 | val nums2 = intArrayOf(2, 5, 6)
42 | Merge().merge(nums1, 3, nums2, 3)
43 | nums1.forEach {
44 | println(it)
45 | }
46 | }
47 | }
48 |
49 | fun merge(nums1: IntArray, m: Int, nums2: IntArray, n: Int) {
50 | var i = m - 1
51 | var j = n - 1
52 |
53 | while (i >= 0 && j >= 0) {
54 | if (nums1[i] <= nums2[j]) {
55 | nums1[i + j + 1] = nums2[j--]
56 | } else {
57 | nums1[i + j + 1] = nums1[i--]
58 | }
59 | }
60 | while (j >= 0) {
61 | nums1[i + j + 1] = nums2[j--]
62 | }
63 | }
64 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/PermuteUnique.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | /**
4 | * 全排列 II
5 | * 给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
6 | */
7 | class PermuteUnique {
8 |
9 | companion object {
10 | @JvmStatic
11 | fun main(args: Array) {
12 | PermuteUnique().permuteUnique(
13 | intArrayOf(1, 1, 2)
14 | ).forEach {
15 | println("$it")
16 | }
17 | }
18 | }
19 |
20 | private val result = arrayListOf>()
21 | private val temp = arrayListOf()
22 | private var size = 0
23 |
24 | fun permuteUnique(nums: IntArray): List> {
25 | size = nums.size
26 | if (size == 0) return result
27 | nums.sort()
28 | val visits = BooleanArray(size)
29 | backtrace(nums, visits, 0)
30 | return result
31 | }
32 |
33 | /**
34 | * O(n * n!)
35 | * O(n)
36 | */
37 | private fun backtrace(nums: IntArray, visits: BooleanArray, index: Int) {
38 | if (index == size) {
39 | result.add(ArrayList(temp))
40 | return
41 | }
42 | for (i in 0 until size) {
43 | if (visits[i] || (i > 0 && nums[i] == nums[i - 1] && !visits[i - 1])) {
44 | continue
45 | }
46 | visits[i] = true
47 | temp.add(nums[i])
48 | backtrace(nums, visits, index + 1)
49 | visits[i] = false
50 | temp.removeLast()
51 | }
52 | }
53 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/PlusOne.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | /**
4 | * 66. 加一
5 | */
6 |
7 | /*
8 | 给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。
9 |
10 | 最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。
11 |
12 | 你可以假设除了整数 0 之外,这个整数不会以零开头。
13 |
14 |
15 | 示例 1:
16 |
17 | 输入:digits = [1,2,3]
18 | 输出:[1,2,4]
19 | 解释:输入数组表示数字 123。
20 | 示例 2:
21 |
22 | 输入:digits = [4,3,2,1]
23 | 输出:[4,3,2,2]
24 | 解释:输入数组表示数字 4321。
25 | 示例 3:
26 |
27 | 输入:digits = [0]
28 | 输出:[1]
29 |
30 | 提示:
31 |
32 | 1 <= digits.length <= 100
33 | 0 <= digits[i] <= 9
34 | */
35 | class PlusOne {
36 |
37 | companion object {
38 | @JvmStatic
39 | fun main(args: Array) {
40 | PlusOne().plusOne(intArrayOf(1, 2, 3)).forEach {
41 | println(it)
42 | }
43 | }
44 | }
45 |
46 | fun plusOne(digits: IntArray): IntArray {
47 | val size = digits.size
48 | for (i in size - 1 downTo 0) {
49 | if (digits[i] != 9) {
50 | digits[i]++
51 | for (j in i + 1 until size) {
52 | digits[j] = 0
53 | }
54 | return digits
55 | }
56 | }
57 | val result = IntArray(size + 1)
58 | result[0] = 1
59 | return result
60 | }
61 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/StrStr.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | /**
4 | * 28. 找出字符串中第一个匹配项的下标
5 | */
6 |
7 | /*
8 | 给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。
9 |
10 |
11 |
12 | 示例 1:
13 |
14 | 输入:haystack = "sadbutsad", needle = "sad"
15 | 输出:0
16 | 解释:"sad" 在下标 0 和 6 处匹配。
17 | 第一个匹配项的下标是 0 ,所以返回 0 。
18 | 示例 2:
19 |
20 | 输入:haystack = "leetcode", needle = "leeto"
21 | 输出:-1
22 | 解释:"leeto" 没有在 "leetcode" 中出现,所以返回 -1 。
23 |
24 |
25 | 提示:
26 |
27 | 1 <= haystack.length, needle.length <= 104
28 | haystack 和 needle 仅由小写英文字符组成
29 | */
30 | class StrStr {
31 |
32 | companion object {
33 |
34 | @JvmStatic
35 | fun main(args: Array) {
36 | println(StrStr().strStr("sadbutsad", "sad"))
37 | println(StrStr().strStr("leetcode", "leeto"))
38 | println(StrStr().strStr("aaa", "aaaa"))
39 | println(StrStr().strStr("aafdaae", "aeu"))
40 | }
41 | }
42 |
43 | fun strStr(haystack: String, needle: String): Int {
44 | val hSize = haystack.length
45 | val nSize = needle.length
46 | if (hSize < nSize) return -1
47 |
48 | var i = 0
49 | var start: Int
50 | var end: Int
51 | while (i <= hSize - nSize) {
52 | start = i
53 | end = start + nSize - 1
54 | while (start <= end && haystack[start] == needle[start - i] && haystack[end] == needle[end - i]) {
55 | start++
56 | end--
57 | }
58 | if (start > end) return i
59 | i++
60 | }
61 | return -1
62 | }
63 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/Trap.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | /**
4 | * 42. 接雨水
5 | */
6 |
7 | /*
8 | 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
9 |
10 | 示例 1:
11 |
12 | 输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
13 | 输出:6
14 | 解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。
15 | 示例 2:
16 |
17 | 输入:height = [4,2,0,3,2,5]
18 | 输出:9
19 |
20 |
21 | 提示:
22 |
23 | n == height.length
24 | 1 <= n <= 2 * 104
25 | 0 <= height[i] <= 105
26 | */
27 | class Trap {
28 |
29 | companion object {
30 | @JvmStatic
31 | fun main(args: Array) {
32 | println(Trap().trap(intArrayOf(0,1,0,2,1,0,1,3,2,1,2,1)))
33 | println(Trap().trap(intArrayOf(4,2,0,3,2,5)))
34 | }
35 | }
36 |
37 | fun trap(height: IntArray): Int {
38 | var maxHeight = -1
39 | var maxIndex = 0
40 | var result = 0
41 | for (i in height.indices) {
42 | if (height[i] > maxHeight) {
43 | maxHeight = height[i]
44 | maxIndex = i
45 | }
46 | }
47 |
48 | var temp = Int.MIN_VALUE
49 | for (l in 0 until maxIndex) {
50 | if (height[l] >= temp) {
51 | temp = height[l]
52 | continue
53 | }
54 | result += temp - height[l]
55 | }
56 |
57 | temp = Int.MIN_VALUE
58 | for (r in height.size - 1 downTo maxIndex + 1) {
59 | if (height[r] >= temp) {
60 | temp = height[r]
61 | continue
62 | }
63 | result += temp - height[r]
64 | }
65 | return result
66 | }
67 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/leetcode/top150/WordPattern.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.leetcode.top150
2 |
3 | /**
4 | * 290. 单词规律
5 | */
6 |
7 | /*
8 | 给定一种规律 pattern 和一个字符串 s ,判断 s 是否遵循相同的规律。
9 |
10 | 这里的 遵循 指完全匹配,例如, pattern 里的每个字母和字符串 s 中的每个非空单词之间存在着双向连接的对应规律。
11 |
12 |
13 |
14 | 示例1:
15 |
16 | 输入: pattern = "abba", s = "dog cat cat dog"
17 | 输出: true
18 | 示例 2:
19 |
20 | 输入:pattern = "abba", s = "dog cat cat fish"
21 | 输出: false
22 | 示例 3:
23 |
24 | 输入: pattern = "aaaa", s = "dog cat cat dog"
25 | 输出: false
26 |
27 |
28 | 提示:
29 |
30 | 1 <= pattern.length <= 300
31 | pattern 只包含小写英文字母
32 | 1 <= s.length <= 3000
33 | s 只包含小写英文字母和 ' '
34 | s 不包含 任何前导或尾随对空格
35 | s 中每个单词都被 单个空格 分隔
36 | */
37 | class WordPattern {
38 |
39 | companion object {
40 | @JvmStatic
41 | fun main(args: Array) {
42 | println(WordPattern().wordPattern("abba", "dog cat cat dog"))
43 | println(WordPattern().wordPattern("abba", "dog cat cat fish"))
44 | println(WordPattern().wordPattern("aaaa", "dog cat cat dog"))
45 | }
46 | }
47 |
48 | fun wordPattern(pattern: String, s: String): Boolean {
49 | val pMap = hashMapOf()
50 | val sMap = hashMapOf()
51 | val ss = s.split(" ")
52 | if (ss.size != pattern.length) return false
53 |
54 | for (i in pattern.indices) {
55 | if (pMap.containsKey(pattern[i]) && pMap[pattern[i]] != ss[i] || sMap.containsKey(ss[i]) && sMap[ss[i]] != pattern[i]) return false
56 | pMap[pattern[i]] = ss[i]
57 | sMap[ss[i]] = pattern[i]
58 | }
59 |
60 | return true
61 | }
62 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/linked/LinkedNode.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.linked
2 |
3 | class LinkedNode(var value: T, var next: LinkedNode? = null) {
4 |
5 | fun printAll() {
6 | println("$value")
7 | var temp = next
8 | while (temp != null) {
9 | println(temp.value)
10 | temp = temp.next
11 | }
12 | }
13 |
14 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/linked/algo/Circle.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.linked.algo
2 |
3 | import com.daily.algothrim.linked.LinkedNode
4 |
5 | /**
6 | * 链表中环的检测
7 | * 使用快慢指针,慢指针每次走一步,快指针每次走两步;当快指针等于慢指针时,说明快指针已经领先慢指针一圈,即该链表存在环。
8 | */
9 | class Circle {
10 |
11 | companion object {
12 | @JvmStatic
13 | fun main(args: Array) {
14 | val head = LinkedNode(1)
15 | println(Circle().existCircle(head.apply {
16 | next = LinkedNode(2).apply {
17 | next = LinkedNode(3).apply {
18 | next = LinkedNode(2).apply {
19 | next = LinkedNode(1).apply {
20 | next = head
21 | }
22 | }
23 | }
24 | }
25 | }))
26 | }
27 | }
28 |
29 | /**
30 | * O(n)
31 | */
32 | fun existCircle(linkedList: LinkedNode?): Boolean {
33 |
34 | var slow = linkedList
35 | var fast = linkedList
36 |
37 | while (fast?.next != null) {
38 | slow = slow?.next
39 | fast = fast.next?.next
40 | if (fast == slow) return true
41 | }
42 |
43 | return false
44 | }
45 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/linked/algo/MiddleNode.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.linked.algo
2 |
3 | import com.daily.algothrim.linked.LinkedNode
4 |
5 | /**
6 | * 求链表的中间结点
7 | * 快慢指针
8 | */
9 | class MiddleNode {
10 |
11 | companion object {
12 | @JvmStatic
13 | fun main(args: Array) {
14 | MiddleNode().middle(LinkedNode("a").apply {
15 | next = LinkedNode("b").apply {
16 | next = LinkedNode("c").apply {
17 | next = LinkedNode("d").apply {
18 | next = LinkedNode("e").apply {
19 | next = LinkedNode("f")
20 | }
21 | }
22 | }
23 | }
24 | })?.printAll()
25 | }
26 | }
27 |
28 | /**
29 | * O(n)
30 | */
31 | private fun middle(singleLinked: LinkedNode?): LinkedNode? {
32 | var fast = singleLinked
33 | var slow = singleLinked
34 |
35 | while (fast?.next?.next != null) {
36 | fast = fast.next?.next
37 | slow = slow?.next
38 | }
39 |
40 | return slow
41 | }
42 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/linked/algo/Reversal.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.linked.algo
2 |
3 | import com.daily.algothrim.linked.LinkedNode
4 |
5 | /**
6 | * 单链表反转
7 | */
8 | class Reversal {
9 |
10 | companion object {
11 | @JvmStatic
12 | fun main(args: Array) {
13 | Reversal().reversal(LinkedNode("a").apply {
14 | next = LinkedNode("b").apply {
15 | next = LinkedNode("c").apply {
16 | next = LinkedNode("d").apply {
17 | next = LinkedNode("a")
18 | }
19 | }
20 | }
21 | })?.printAll()
22 | }
23 | }
24 |
25 | /**
26 | * O(n)
27 | */
28 | fun reversal(singleLinked: LinkedNode?): LinkedNode? {
29 | var result: LinkedNode? = null
30 | var current = singleLinked
31 | var next: LinkedNode?
32 |
33 | while (current != null) {
34 | next = current.next
35 | current.next = result
36 | result = current
37 | current = next
38 | }
39 | return result
40 | }
41 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/lookup/BinarySearch.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.lookup
2 |
3 | /**
4 | * 二分查找
5 | */
6 | class BinarySearch {
7 | companion object {
8 | @JvmStatic
9 | fun main(args: Array) {
10 | val a = intArrayOf(1, 2, 4, 5, 6, 9, 29, 93, 95, 213, 741)
11 | println(BinarySearch().search(a, a.size, 93))
12 | }
13 | }
14 |
15 | /**
16 | * O(log n)
17 | */
18 | fun search(a: IntArray, n: Int, value: Int): Int {
19 | var low = 0
20 | var high = n - 1
21 |
22 | while (low <= high) {
23 | val mid = low + (high - low).shr(1)
24 | when {
25 | a[mid] < value -> {
26 | low = mid + 1
27 | }
28 | a[mid] > value -> {
29 | high = mid - 1
30 | }
31 | else -> {
32 | return mid
33 | }
34 | }
35 | }
36 | return -1
37 | }
38 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/lookup/BinarySearchV1.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.lookup
2 |
3 | /**
4 | * 二分查找第一个等于给定的值
5 | */
6 | class BinarySearchV1 {
7 |
8 | companion object {
9 | @JvmStatic
10 | fun main(args: Array) {
11 | val a = intArrayOf(1, 2, 4, 5, 6, 9, 29, 93, 93, 93, 95, 213, 741)
12 | println(BinarySearchV1().search(a, a.size, 93))
13 | }
14 | }
15 |
16 | /**
17 | * O(log n)
18 | */
19 | fun search(a: IntArray, n: Int, value: Int): Int {
20 | var low = 0
21 | var high = n - 1
22 | while (low <= high) {
23 | val mid = low + (high - low).shr(1)
24 | when {
25 | a[mid] < value -> {
26 | low = mid + 1
27 | }
28 | a[mid] > value -> {
29 | high = mid - 1
30 | }
31 | else -> {
32 | if (mid == 0 || a[mid - 1] != value) return mid
33 | high = mid - 1
34 | }
35 | }
36 | }
37 |
38 | return -1
39 | }
40 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/lookup/BinarySearchV2.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.lookup
2 |
3 | /**
4 | * 二分法查找最后一个值等于给定的值
5 | */
6 | class BinarySearchV2 {
7 |
8 | companion object {
9 | @JvmStatic
10 | fun main(args: Array) {
11 | val a = intArrayOf(1, 2, 4, 5, 6, 9, 29, 93, 93, 93, 95, 213, 741)
12 | println(BinarySearchV2().search(a, a.size, 93))
13 | }
14 | }
15 |
16 | /**
17 | * O(log n)
18 | */
19 | fun search(a: IntArray, n: Int, value: Int): Int {
20 | var low = 0
21 | var high = n - 1
22 |
23 | while (low <= high) {
24 | val mid = low + (high - low).shr(1)
25 | when {
26 | a[mid] < value -> {
27 | low = mid + 1
28 | }
29 | a[mid] > value -> {
30 | high = mid - 1
31 | }
32 | else -> {
33 | if (mid == n - 1 || a[mid + 1] != value) return mid
34 | low = mid + 1
35 | }
36 | }
37 | }
38 |
39 | return -1
40 | }
41 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/lookup/BinarySearchV3.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.lookup
2 |
3 | /**
4 | * 二分查找第一个大于等于给定的值
5 | */
6 | class BinarySearchV3 {
7 |
8 | companion object {
9 | @JvmStatic
10 | fun main(args: Array) {
11 | val a = intArrayOf(1, 2, 4, 5, 6, 9, 29, 93, 93, 93, 95, 213, 741)
12 | println(BinarySearchV3().search(a, a.size, 93))
13 | }
14 | }
15 |
16 | /**
17 | * O(log n)
18 | */
19 | fun search(a: IntArray, n: Int, value: Int): Int {
20 | var low = 0
21 | var high = n - 1
22 |
23 | while (low <= high) {
24 | val mid = low + (high - low).shr(1)
25 | when {
26 | a[mid] >= value -> {
27 | if (mid == 0 || a[mid - 1] < value) return mid
28 | high = mid - 1
29 | }
30 | else -> {
31 | low = mid + 1
32 | }
33 | }
34 | }
35 |
36 | return -1
37 | }
38 |
39 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/lookup/BinarySearchV4.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.lookup
2 |
3 | /**
4 | * 二分查找最后一个小于等于给定的值
5 | */
6 | class BinarySearchV4 {
7 |
8 | companion object {
9 | @JvmStatic
10 | fun main(args: Array) {
11 | val a = intArrayOf(1, 2, 4, 5, 6, 9, 29, 93, 93, 93, 95, 213, 741)
12 | println(BinarySearchV4().search(a, a.size, 93))
13 | }
14 | }
15 |
16 | /**
17 | * O(log n)
18 | */
19 | fun search(a: IntArray, n: Int, value: Int): Int {
20 | var low = 0
21 | var high = n - 1
22 | while (low <= high) {
23 | val mid = low + (high - low).shr(1)
24 | when {
25 | a[mid] <= value -> {
26 | if (mid == n - 1 || a[mid + 1] > value) return mid
27 | low = mid + 1
28 | }
29 | else -> {
30 | high = mid - 1
31 | }
32 | }
33 | }
34 |
35 | return -1
36 | }
37 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/queue/CircleQueue.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.queue
2 |
3 | /**
4 | * 基于数组的循环队列
5 | */
6 | class CircleQueue(capacity: Int) {
7 |
8 | private var n = capacity
9 | private var head = 0
10 | private var tail = 0
11 | private var queue = arrayOfNulls(capacity)
12 |
13 | fun enqueue(item: String): Boolean {
14 | // 队满,会浪费一个存储空间
15 | if ((tail + 1) % n == head) return false
16 | queue[tail] = item
17 | tail = (tail + 1) % n
18 | return true
19 | }
20 |
21 | fun dequeue(): String? {
22 | if (tail == head) return null
23 | val item = queue[head]
24 | head = (head + 1) % n
25 | return item
26 | }
27 |
28 | companion object {
29 |
30 | @JvmStatic
31 | fun main(args: Array) {
32 | CircleQueue(6).apply {
33 | println(enqueue("1"))
34 | println(enqueue("2"))
35 | println(dequeue())
36 | println(enqueue("3"))
37 | println(enqueue("4"))
38 | println(dequeue())
39 | println(dequeue())
40 | println(enqueue("5"))
41 | println(dequeue())
42 | println(enqueue("6"))
43 | println(enqueue("7"))
44 | println(enqueue("8"))
45 | println(enqueue("9"))
46 | println(enqueue("10"))
47 | }
48 | }
49 | }
50 |
51 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/recursion/KthGrammar.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.recursion
2 |
3 | /**
4 | * 第K个语法符号(LeetCode 779)
5 | *
6 | * 在第一行我们写上一个 0。接下来的每一行,将前一行中的0替换为01,1替换为10。
7 | *
8 | * 给定行数N和序数 K,返回第 N 行中第 K个字符。(K从1开始)
9 | *
10 | * 例子:
11 | *
12 | * 输入: N = 1, K = 1
13 | * 输出: 0
14 | *
15 | * 输入: N = 2, K = 1
16 | * 输出: 0
17 | *
18 | * 输入: N = 2, K = 2
19 | * 输出: 1
20 | *
21 | * 输入: N = 4, K = 5
22 | * 输出: 1
23 | *
24 | * 解释:
25 | * 第一行: 0
26 | * 第二行: 01
27 | * 第三行: 0110
28 | * 第四行: 01101001
29 | *
30 | * 注意:
31 | *
32 | * N的范围[1, 30].
33 | * K的范围[1, 2^(N-1)].
34 | *
35 | */
36 | class KthGrammar {
37 |
38 | companion object {
39 | @JvmStatic
40 | fun main(args: Array) {
41 | println(KthGrammar().kthGrammar(4, 5))
42 | println(KthGrammar().kthGrammarReverse(4, 5))
43 | }
44 | }
45 |
46 | // 第一行: 0
47 | // 第二行: 01
48 | // 第三行: 0110
49 | // 第四行: 01101001
50 |
51 | // 第 K 个数字是上一行第 (K+1) / 2 个数字生成的。如果上一行的数字为 0,被生成的数字为 1 - (K%2),如果上一行的数字为 1,被生成的数字为 K%2
52 | // O(n)
53 | private fun kthGrammar(N: Int, K: Int): Int {
54 | if (N == 1) return 0
55 | return (K.inv() and 1) xor kthGrammar(N - 1, (K + 1) / 2)
56 | }
57 |
58 | // 每一行前一半部分等于上一行,后一半部分等于上一行的 0 1 反转
59 | // O(n)
60 | private fun kthGrammarReverse(N: Int, K: Int): Int {
61 | if (N == 1) return 0
62 | // K位于前一半部分
63 | if (K <= (1 shl (N - 2))) {
64 | return kthGrammarReverse(N - 1, K)
65 | }
66 | // K 位于后一半部分
67 | return kthGrammarReverse(N - 1, K - (1 shl (N - 1))) xor 1
68 | }
69 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/sort/BubbleSort.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.sort
2 |
3 | /**
4 | * 冒泡排序
5 | * 稳定排序
6 | * 原地排序
7 | */
8 | class BubbleSort {
9 | companion object {
10 | @JvmStatic
11 | fun main(args: Array) {
12 | val a = intArrayOf(10, 1, 4, 2, 5, 643, 654, 234, 2)
13 | BubbleSort().sort(a, a.size)
14 | a.forEach {
15 | println(it)
16 | }
17 | println()
18 | val b = intArrayOf(10, 1, 4, 2, 5, 643, 654, 234, 2)
19 | BubbleSort().optSort(b, b.size)
20 | b.forEach {
21 | println(it)
22 | }
23 | }
24 | }
25 |
26 | /**
27 | * O(n2)
28 | */
29 | fun sort(a: IntArray, n: Int) {
30 | var i = 0
31 | while (i < n) {
32 | var j = 0
33 | while (j < n - 1 - i) {
34 | if (a[j] > a[j + 1]) {
35 | val temp = a[j]
36 | a[j] = a[j + 1]
37 | a[j + 1] = temp
38 | }
39 | j++
40 | }
41 | i++
42 | }
43 | }
44 |
45 | fun optSort(a: IntArray, n: Int) {
46 | var i = 0
47 | while (i < n) {
48 | var j = 0
49 | var flag = false
50 | while (j < n - 1 - i) {
51 | if (a[j] > a[j + 1]) {
52 | val temp = a[j]
53 | a[j] = a[j + 1]
54 | a[j + 1] = temp
55 | flag = true
56 | }
57 | j++
58 | }
59 | if (!flag) break
60 | i++
61 | }
62 | }
63 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/sort/CountSort.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.sort
2 |
3 | /**
4 | * 计数排序
5 | * 稳定排序
6 | * 非原地排序
7 | */
8 | class CountSort {
9 | companion object {
10 | @JvmStatic
11 | fun main(args: Array) {
12 | val a = intArrayOf(3, 2, 4, 3, 5, 3, 2, 1, 5, 0, 0, 4, 6)
13 | CountSort().sort(a, a.size)
14 | a.forEach {
15 | println(it)
16 | }
17 | }
18 | }
19 |
20 | /**
21 | * O(n)
22 | */
23 | fun sort(a: IntArray, n: Int) {
24 | // 找到数据范围
25 | var max = 0
26 | a.forEach {
27 | if (it > max) max = it
28 | }
29 |
30 | // 统计每个值的个数
31 | val c = IntArray(max + 1)
32 | a.forEach {
33 | c[it]++
34 | }
35 |
36 | // 每个值的个数求和
37 | for (i in 1 until max + 1) {
38 | c[i] = c[i] + c[i - 1]
39 | }
40 |
41 | // 排序到临时temp数组中
42 | var j = n - 1
43 | val temp = IntArray(n)
44 | while (j >= 0) {
45 | temp[c[a[j]] - 1] = a[j]
46 | c[a[j]]--
47 | j--
48 | }
49 |
50 | // 转移到a中
51 | temp.forEachIndexed { index, i ->
52 | a[index] = i
53 | }
54 |
55 | }
56 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/sort/HeapSort.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.sort
2 |
3 | /**
4 | * 堆排序
5 | * 不稳定排序(存在不相邻交换数据)
6 | * 原地排序
7 | *
8 | * 数据交换次数比快速排序多,但排序时间复杂度相对稳定。
9 | * 堆使用数组存储是间隔的,所以对于cpu缓存不友好
10 | */
11 | class HeapSort {
12 |
13 | companion object {
14 | @JvmStatic
15 | fun main(args: Array) {
16 | // -1为占位符, 堆下标从1开始
17 | val a = intArrayOf(-1, 1, 5, 6, 2, 4, 93, 289, 534, 2, 3)
18 | HeapSort().sort(a, a.size)
19 | a.forEach {
20 | println(it)
21 | }
22 | }
23 | }
24 |
25 |
26 | /**
27 | * O(nlog n)
28 | */
29 | fun sort(a: IntArray, n: Int) {
30 | // 建堆
31 | buildHeap(a, n)
32 | var k = n - 1
33 |
34 | // 排序
35 | while (k > 1) {
36 | swap(a, 1, k)
37 | // 堆化
38 | heapify(a, 1, --k)
39 | }
40 |
41 | }
42 |
43 |
44 | /**
45 | * O(n)
46 | */
47 | private fun buildHeap(a: IntArray, n: Int) {
48 | var i = n / 2
49 | while (i >= 1) {
50 | heapify(a, i--, n)
51 | }
52 | }
53 |
54 | /**
55 | * O(log n)
56 | */
57 | private fun heapify(a: IntArray, pos: Int, n: Int) {
58 | var i = pos
59 | while (true) {
60 | var j = i
61 | if (2 * i < n && a[j] < a[2 * i]) j = 2 * i
62 | if (2 * i + 1 < n && a[j] < a[2 * i + 1]) j = 2 * i + 1
63 | if (j == i) break
64 | swap(a, i, j)
65 | i = j
66 | }
67 | }
68 |
69 | private fun swap(a: IntArray, i: Int, j: Int) {
70 | val temp = a[i]
71 | a[i] = a[j]
72 | a[j] = temp
73 | }
74 |
75 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/sort/InsertSort.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.sort
2 |
3 | /**
4 | * 插入排序
5 | * 原地排序
6 | * 稳定排序
7 | */
8 | class InsertSort {
9 |
10 | companion object {
11 | @JvmStatic
12 | fun main(args: Array) {
13 | val a = intArrayOf(10, 1, 4, 2, 5, 643, 654, 234, 2)
14 | InsertSort().sort(a, a.size)
15 | a.forEach {
16 | println(it)
17 | }
18 | }
19 | }
20 |
21 | /**
22 | * O(n2)
23 | */
24 | fun sort(a: IntArray, n: Int) {
25 | var i = 1
26 | while (i < n) {
27 | var j = i - 1
28 | val value = a[i]
29 | while (j >= 0) {
30 | if (value < a[j]) {
31 | a[j + 1] = a[j]
32 | } else {
33 | break
34 | }
35 | j--
36 | }
37 | a[j + 1] = value
38 | i++
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/sort/MergeSort.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.sort
2 |
3 |
4 | /**
5 | * 归并排序
6 | * 稳定排序
7 | * 不是原地排序
8 | */
9 | class MergeSort {
10 | companion object {
11 | @JvmStatic
12 | fun main(args: Array) {
13 | val a = intArrayOf(10, 1, 4, 2, 5, 643, 654, 234, 2)
14 | MergeSort().sort(a, 0, a.size - 1)
15 | a.forEach {
16 | println(it)
17 | }
18 | }
19 | }
20 |
21 | /**
22 | * 时间复杂度: O(nlog n)
23 | * 空间复杂度: O(n)
24 | */
25 | private fun sort(a: IntArray, start: Int, end: Int) {
26 | if (start < end) {
27 | val mid = (start + end) / 2
28 | // 分治递归
29 | sort(a, start, mid)
30 | sort(a, mid + 1, end)
31 | // 合并
32 | merge(a, start, end)
33 | }
34 | }
35 |
36 | private fun merge(a: IntArray, start: Int, end: Int) {
37 | val mid = (start + end) / 2
38 | var i = start
39 | var j = mid + 1
40 | var k = 0
41 | val temp = IntArray(end - start + 1)
42 | while (i <= mid && j <= end) {
43 | if (a[i] < a[j]) {
44 | temp[k++] = a[i++]
45 | } else {
46 | temp[k++] = a[j++]
47 | }
48 | }
49 |
50 | // i有剩余
51 | while (i <= mid) {
52 | temp[k++] = a[i++]
53 | }
54 |
55 | // j有剩余
56 | while (j <= end) {
57 | temp[k++] = a[j++]
58 | }
59 |
60 | // 将temp转移到a中
61 | temp.forEachIndexed { index, item ->
62 | a[start + index] = item
63 | }
64 | }
65 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/sort/QuickSort.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.sort
2 |
3 | /**
4 | * 快速排序
5 | * 不稳定排序
6 | * 原地排序
7 | */
8 | class QuickSort {
9 | companion object {
10 | @JvmStatic
11 | fun main(args: Array) {
12 | val a = intArrayOf(10, 1, 4, 2, 5, 643, 654, 234, 2)
13 | QuickSort().quick(a, 0, a.size - 1)
14 | a.forEach {
15 | println(it)
16 | }
17 | }
18 | }
19 |
20 | /**
21 | * 时间复制度O(nlog n); 最好时间复杂度O(nlog n); 最坏时间复杂度O(n2)
22 | * 空间复杂度O(1)
23 | */
24 | private fun quick(a: IntArray, start: Int, end: Int) {
25 | if (start < end) {
26 | // 找到分区位置
27 | val mid = sort(a, start, end)
28 | // 分区
29 | quick(a, start, mid - 1)
30 | quick(a, mid + 1, end)
31 | }
32 | }
33 |
34 | private fun sort(a: IntArray, start: Int, end: Int): Int {
35 | val pivot = a[end]
36 | var i = start
37 | var j = start
38 |
39 | while (j < end) {
40 | if (a[j] < pivot) {
41 | val temp = a[i]
42 | a[i] = a[j]
43 | a[j] = temp
44 | i++
45 | }
46 | j++
47 | }
48 |
49 | val temp = a[i]
50 | a[i] = pivot
51 | a[end] = temp
52 |
53 | return i
54 | }
55 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/sort/SelectSort.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.sort
2 |
3 | /**
4 | * 选择排序
5 | * 不稳定排序
6 | * 原地排序
7 | */
8 | class SelectSort {
9 |
10 | companion object {
11 | @JvmStatic
12 | fun main(args: Array) {
13 | val a = intArrayOf(10, 1, 4, 2, 5, 643, 654, 234, 2)
14 | SelectSort().sort(a, a.size)
15 | a.forEach {
16 | println(it)
17 | }
18 | }
19 | }
20 |
21 | /**
22 | * O(n2)
23 | */
24 | fun sort(a: IntArray, n: Int) {
25 | var i = 0
26 | while (i < n) {
27 | var j = i + 1
28 | var k = i
29 | var min = a[i]
30 | while (j < n) {
31 | if (a[j] < min) {
32 | min = a[j]
33 | k = j
34 | }
35 | j++
36 | }
37 | a[k] = a[i]
38 | a[i] = min
39 | i++
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/stack/MinStack.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.stack
2 |
3 | import java.util.*
4 |
5 |
6 | /**
7 | * 设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。(LeetCode 155)
8 | * push(x) —— 将元素 x 推入栈中。
9 | * pop()—— 删除栈顶的元素。
10 | * top()—— 获取栈顶元素。
11 | * getMin() —— 检索栈中的最小元素。
12 | *
13 | * 使用辅助栈,每次操作都与实际栈一一对应,只不过每次push的都是实际值与辅助栈顶值中的最小值
14 | * */
15 | class MinStack {
16 | companion object {
17 | @JvmStatic
18 | fun main(args: Array) {
19 | val minStack = MinStack()
20 | minStack.push(-2)
21 | minStack.push(0)
22 | minStack.push(-3)
23 | println(minStack.getMin())
24 | minStack.pop()
25 | println(minStack.top())
26 | println(minStack.getMin())
27 | }
28 | }
29 |
30 | private val mStack = Stack()
31 | private val mMinStack = Stack()
32 |
33 | fun push(item: Int) {
34 | mStack.push(item)
35 | if (mMinStack.isEmpty() || item < mMinStack.peek()) {
36 | mMinStack.push(item)
37 | } else {
38 | mMinStack.push(mMinStack.peek())
39 | }
40 | }
41 |
42 | fun pop() {
43 | mMinStack.pop()
44 | mStack.pop()
45 | }
46 |
47 | fun top(): Int {
48 | return mStack.peek()
49 | }
50 |
51 | fun getMin(): Int {
52 | return mMinStack.peek()
53 | }
54 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/stack/ValidParenthesis.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.stack
2 |
3 | import java.util.*
4 |
5 | /**
6 | * 有效的括号(LeetCode 20)
7 | * 给定一个只包括 '(',')','{','}','[',']'的字符串,判断字符串是否有效。
8 | * 有效字符串需满足:
9 | *
10 | * 左括号必须用相同类型的右括号闭合。
11 | * 左括号必须以正确的顺序闭合。
12 | * 注意空字符串可被认为是有效字符串。
13 | *
14 | * 使用栈实现,遍历字符串,遇到左括号统统入栈,遇到有括号
15 | * 1. 判断栈是否为空,为空则无效
16 | * 2. 从栈中取出一个元素,与当前右括号做匹配,不符合则无效,符合则继续向下操作
17 | * 3. 字符串遍历结束之后,判断栈是否为空,不为空则无效。
18 | */
19 | class ValidParenthesis {
20 |
21 | companion object {
22 | @JvmStatic
23 | fun main(args: Array) {
24 | println(ValidParenthesis().isValid("({[[{(([]))}]]})"))
25 | }
26 | }
27 |
28 | /**
29 | * O(n)
30 | */
31 | private fun isValid(s: String): Boolean {
32 | val stack = Stack()
33 | s.forEach {
34 | if (it == '(' || it == '{' || it == '[') {
35 | stack.push(it)
36 | } else {
37 | if (stack.isEmpty()) return false
38 | val popItem = stack.pop()
39 | if ((popItem == '(' && it != ')')
40 | || (popItem == '{' && it != '}')
41 | || (popItem == '[' && it != ']')) return false
42 | }
43 | }
44 |
45 | if (stack.isNotEmpty()) return false
46 |
47 | return true
48 | }
49 | }
--------------------------------------------------------------------------------
/kotlin/src/com/daily/algothrim/sword/Permutation.kt:
--------------------------------------------------------------------------------
1 | package com.daily.algothrim.sword
2 |
3 | /**
4 | * 剑指 Offer 38. 字符串的排列
5 | *
6 | * 输入一个字符串,打印出该字符串中字符的所有排列。
7 | *
8 | * 你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。
9 | */
10 | class Permutation {
11 |
12 | companion object {
13 | @JvmStatic
14 | fun main(args: Array) {
15 | val result = Permutation().permutation("abc")
16 | result.forEach {
17 | println(it)
18 | }
19 | }
20 | }
21 |
22 | fun permutation(s: String): Array