mirror of
https://github.com/krahets/hello-algo.git
synced 2026-08-22 00:07:13 +00:00
Many bug fixes and improvements (#1270)
* Add Ruby and Kotlin icons Add the avatar of @curtishd * Update README * Synchronize zh-hant and zh versions. * Translate the pythontutor blocks to traditional Chinese * Fix en/mkdocs.yml * Update the landing page of the en version. * Fix the Dockerfile * Refine the en landingpage * Fix en landing page * Reset the README.md
This commit is contained in:
@@ -55,7 +55,7 @@ fun traverse(nums: IntArray) {
|
||||
count += nums[i]
|
||||
}
|
||||
// 直接走訪陣列元素
|
||||
for (j: Int in nums) {
|
||||
for (j in nums) {
|
||||
count += j
|
||||
}
|
||||
}
|
||||
@@ -63,7 +63,8 @@ fun traverse(nums: IntArray) {
|
||||
/* 在陣列中查詢指定元素 */
|
||||
fun find(nums: IntArray, target: Int): Int {
|
||||
for (i in nums.indices) {
|
||||
if (nums[i] == target) return i
|
||||
if (nums[i] == target)
|
||||
return i
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ package chapter_array_and_linkedlist
|
||||
import utils.ListNode
|
||||
import utils.printLinkedList
|
||||
|
||||
/* 在鏈結串列的節點 n0 之後插入節點p */
|
||||
/* 在鏈結串列的節點 n0 之後插入節點 P */
|
||||
fun insert(n0: ListNode?, p: ListNode?) {
|
||||
val n1 = n0?.next
|
||||
p?.next = n1
|
||||
@@ -18,16 +18,20 @@ fun insert(n0: ListNode?, p: ListNode?) {
|
||||
|
||||
/* 刪除鏈結串列的節點 n0 之後的首個節點 */
|
||||
fun remove(n0: ListNode?) {
|
||||
val p = n0?.next
|
||||
if (n0?.next == null)
|
||||
return
|
||||
val p = n0.next
|
||||
val n1 = p?.next
|
||||
n0?.next = n1
|
||||
n0.next = n1
|
||||
}
|
||||
|
||||
/* 訪問鏈結串列中索引為 index 的節點 */
|
||||
fun access(head: ListNode?, index: Int): ListNode? {
|
||||
var h = head
|
||||
for (i in 0..<index) {
|
||||
h = h?.next
|
||||
if (h == null)
|
||||
return null
|
||||
h = h.next
|
||||
}
|
||||
return h
|
||||
}
|
||||
@@ -37,7 +41,8 @@ fun find(head: ListNode?, target: Int): Int {
|
||||
var index = 0
|
||||
var h = head
|
||||
while (h != null) {
|
||||
if (h.value == target) return index
|
||||
if (h._val == target)
|
||||
return index
|
||||
h = h.next
|
||||
index++
|
||||
}
|
||||
@@ -46,6 +51,7 @@ fun find(head: ListNode?, target: Int): Int {
|
||||
|
||||
/* Driver Code */
|
||||
fun main() {
|
||||
/* 初始化鏈結串列 */
|
||||
// 初始化各個節點
|
||||
val n0 = ListNode(1)
|
||||
val n1 = ListNode(3)
|
||||
@@ -60,7 +66,8 @@ fun main() {
|
||||
n3.next = n4
|
||||
println("初始化的鏈結串列為")
|
||||
printLinkedList(n0)
|
||||
|
||||
|
||||
/* 插入節點 */
|
||||
insert(n0, ListNode(0))
|
||||
println("插入節點後的鏈結串列為")
|
||||
printLinkedList(n0)
|
||||
@@ -72,7 +79,7 @@ fun main() {
|
||||
|
||||
/* 訪問節點 */
|
||||
val node: ListNode = access(n0, 3)!!
|
||||
println("鏈結串列中索引 3 處的節點的值 = ${node.value}")
|
||||
println("鏈結串列中索引 3 處的節點的值 = ${node._val}")
|
||||
|
||||
/* 查詢節點 */
|
||||
val index: Int = find(n0, 2)
|
||||
|
||||
@@ -8,9 +8,9 @@ package chapter_array_and_linkedlist
|
||||
|
||||
/* Driver Code */
|
||||
fun main() {
|
||||
/* 初始化串列 */
|
||||
// 可變集合
|
||||
val numbers = mutableListOf(1, 3, 2, 5, 4)
|
||||
val nums = ArrayList<Int>(numbers)
|
||||
val nums = mutableListOf(1, 3, 2, 5, 4)
|
||||
println("串列 nums = $nums")
|
||||
|
||||
/* 訪問元素 */
|
||||
@@ -53,11 +53,11 @@ fun main() {
|
||||
}
|
||||
|
||||
/* 拼接兩個串列*/
|
||||
val nums1 = ArrayList<Int>(listOf(6, 8, 7, 10, 9))
|
||||
val nums1 = mutableListOf(6, 8, 7, 10, 9)
|
||||
nums.addAll(nums1)
|
||||
println("將串列 nums1 拼接到 nums 之後,得到 nums = $nums")
|
||||
|
||||
/* 排序串列 */
|
||||
nums.sort() //排序後,串列元素從小到大排列
|
||||
nums.sort()
|
||||
println("排序串列後 nums = $nums")
|
||||
}
|
||||
@@ -9,9 +9,9 @@ package chapter_array_and_linkedlist
|
||||
/* 串列類別 */
|
||||
class MyList {
|
||||
private var arr: IntArray = intArrayOf() // 陣列(儲存串列元素)
|
||||
private var capacity = 10 // 串列容量
|
||||
private var size = 0 // 串列長度(當前元素數量)
|
||||
private var extendRatio = 2 // 每次串列擴容的倍數
|
||||
private var capacity: Int = 10 // 串列容量
|
||||
private var size: Int = 0 // 串列長度(當前元素數量)
|
||||
private var extendRatio: Int = 2 // 每次串列擴容的倍數
|
||||
|
||||
/* 建構子 */
|
||||
init {
|
||||
@@ -32,7 +32,7 @@ class MyList {
|
||||
fun get(index: Int): Int {
|
||||
// 索引如果越界,則丟擲異常,下同
|
||||
if (index < 0 || index >= size)
|
||||
throw IndexOutOfBoundsException()
|
||||
throw IndexOutOfBoundsException("索引越界")
|
||||
return arr[index]
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ class MyList {
|
||||
fun remove(index: Int): Int {
|
||||
if (index < 0 || index >= size)
|
||||
throw IndexOutOfBoundsException("索引越界")
|
||||
val num: Int = arr[index]
|
||||
val num = arr[index]
|
||||
// 將將索引 index 之後的元素都向前移動一位
|
||||
for (j in index..<size - 1)
|
||||
arr[j] = arr[j + 1]
|
||||
|
||||
@@ -10,17 +10,17 @@ package chapter_backtracking.n_queens
|
||||
fun backtrack(
|
||||
row: Int,
|
||||
n: Int,
|
||||
state: List<MutableList<String>>,
|
||||
res: MutableList<List<List<String>>?>,
|
||||
state: MutableList<MutableList<String>>,
|
||||
res: MutableList<MutableList<MutableList<String>>?>,
|
||||
cols: BooleanArray,
|
||||
diags1: BooleanArray,
|
||||
diags2: BooleanArray
|
||||
) {
|
||||
// 當放置完所有行時,記錄解
|
||||
if (row == n) {
|
||||
val copyState: MutableList<List<String>> = ArrayList()
|
||||
val copyState = mutableListOf<MutableList<String>>()
|
||||
for (sRow in state) {
|
||||
copyState.add(ArrayList(sRow))
|
||||
copyState.add(sRow.toMutableList())
|
||||
}
|
||||
res.add(copyState)
|
||||
return
|
||||
@@ -49,11 +49,11 @@ fun backtrack(
|
||||
}
|
||||
|
||||
/* 求解 n 皇后 */
|
||||
fun nQueens(n: Int): List<List<List<String>>?> {
|
||||
fun nQueens(n: Int): MutableList<MutableList<MutableList<String>>?> {
|
||||
// 初始化 n*n 大小的棋盤,其中 'Q' 代表皇后,'#' 代表空位
|
||||
val state: MutableList<MutableList<String>> = ArrayList()
|
||||
val state = mutableListOf<MutableList<String>>()
|
||||
for (i in 0..<n) {
|
||||
val row: MutableList<String> = ArrayList()
|
||||
val row = mutableListOf<String>()
|
||||
for (j in 0..<n) {
|
||||
row.add("#")
|
||||
}
|
||||
@@ -62,7 +62,7 @@ fun nQueens(n: Int): List<List<List<String>>?> {
|
||||
val cols = BooleanArray(n) // 記錄列是否有皇后
|
||||
val diags1 = BooleanArray(2 * n - 1) // 記錄主對角線上是否有皇后
|
||||
val diags2 = BooleanArray(2 * n - 1) // 記錄次對角線上是否有皇后
|
||||
val res: MutableList<List<List<String>>?> = ArrayList()
|
||||
val res = mutableListOf<MutableList<MutableList<String>>?>()
|
||||
|
||||
backtrack(0, n, state, res, cols, diags1, diags2)
|
||||
|
||||
@@ -72,7 +72,7 @@ fun nQueens(n: Int): List<List<List<String>>?> {
|
||||
/* Driver Code */
|
||||
fun main() {
|
||||
val n = 4
|
||||
val res: List<List<List<String?>?>?> = nQueens(n)
|
||||
val res = nQueens(n)
|
||||
|
||||
println("輸入棋盤長寬為 $n")
|
||||
println("皇后放置方案共有 ${res.size} 種")
|
||||
|
||||
@@ -11,11 +11,11 @@ fun backtrack(
|
||||
state: MutableList<Int>,
|
||||
choices: IntArray,
|
||||
selected: BooleanArray,
|
||||
res: MutableList<List<Int>?>
|
||||
res: MutableList<MutableList<Int>?>
|
||||
) {
|
||||
// 當狀態長度等於元素數量時,記錄解
|
||||
if (state.size == choices.size) {
|
||||
res.add(ArrayList(state))
|
||||
res.add(state.toMutableList())
|
||||
return
|
||||
}
|
||||
// 走訪所有選擇
|
||||
@@ -36,9 +36,9 @@ fun backtrack(
|
||||
}
|
||||
|
||||
/* 全排列 I */
|
||||
fun permutationsI(nums: IntArray): List<List<Int>?> {
|
||||
val res: MutableList<List<Int>?> = ArrayList()
|
||||
backtrack(ArrayList(), nums, BooleanArray(nums.size), res)
|
||||
fun permutationsI(nums: IntArray): MutableList<MutableList<Int>?> {
|
||||
val res = mutableListOf<MutableList<Int>?>()
|
||||
backtrack(mutableListOf(), nums, BooleanArray(nums.size), res)
|
||||
return res
|
||||
}
|
||||
|
||||
|
||||
@@ -15,11 +15,11 @@ fun backtrack(
|
||||
) {
|
||||
// 當狀態長度等於元素數量時,記錄解
|
||||
if (state.size == choices.size) {
|
||||
res.add(ArrayList(state))
|
||||
res.add(state.toMutableList())
|
||||
return
|
||||
}
|
||||
// 走訪所有選擇
|
||||
val duplicated: MutableSet<Int> = HashSet()
|
||||
val duplicated = HashSet<Int>()
|
||||
for (i in choices.indices) {
|
||||
val choice = choices[i]
|
||||
// 剪枝:不允許重複選擇元素 且 不允許重複選擇相等元素
|
||||
@@ -39,15 +39,14 @@ fun backtrack(
|
||||
|
||||
/* 全排列 II */
|
||||
fun permutationsII(nums: IntArray): MutableList<MutableList<Int>?> {
|
||||
val res: MutableList<MutableList<Int>?> = ArrayList()
|
||||
backtrack(ArrayList(), nums, BooleanArray(nums.size), res)
|
||||
val res = mutableListOf<MutableList<Int>?>()
|
||||
backtrack(mutableListOf(), nums, BooleanArray(nums.size), res)
|
||||
return res
|
||||
}
|
||||
|
||||
/* Driver Code */
|
||||
fun main() {
|
||||
val nums = intArrayOf(1, 2, 2)
|
||||
|
||||
val res = permutationsII(nums)
|
||||
|
||||
println("輸入陣列 nums = ${nums.contentToString()}")
|
||||
|
||||
@@ -16,7 +16,7 @@ fun preOrder(root: TreeNode?) {
|
||||
if (root == null) {
|
||||
return
|
||||
}
|
||||
if (root.value == 7) {
|
||||
if (root._val == 7) {
|
||||
// 記錄解
|
||||
res!!.add(root)
|
||||
}
|
||||
@@ -31,13 +31,13 @@ fun main() {
|
||||
printTree(root)
|
||||
|
||||
// 前序走訪
|
||||
res = ArrayList()
|
||||
res = mutableListOf()
|
||||
preOrder(root)
|
||||
|
||||
println("\n輸出所有值為 7 的節點")
|
||||
val vals: MutableList<Int> = ArrayList()
|
||||
for (node in res as ArrayList<TreeNode>) {
|
||||
vals.add(node.value)
|
||||
val vals = mutableListOf<Int>()
|
||||
for (node in res!!) {
|
||||
vals.add(node._val)
|
||||
}
|
||||
println(vals)
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import utils.TreeNode
|
||||
import utils.printTree
|
||||
|
||||
var path: MutableList<TreeNode>? = null
|
||||
var res: MutableList<List<TreeNode>>? = null
|
||||
var res: MutableList<MutableList<TreeNode>>? = null
|
||||
|
||||
/* 前序走訪:例題二 */
|
||||
fun preOrder(root: TreeNode?) {
|
||||
@@ -19,9 +19,9 @@ fun preOrder(root: TreeNode?) {
|
||||
}
|
||||
// 嘗試
|
||||
path!!.add(root)
|
||||
if (root.value == 7) {
|
||||
if (root._val == 7) {
|
||||
// 記錄解
|
||||
res!!.add(ArrayList(path!!))
|
||||
res!!.add(path!!.toMutableList())
|
||||
}
|
||||
preOrder(root.left)
|
||||
preOrder(root.right)
|
||||
@@ -36,16 +36,16 @@ fun main() {
|
||||
printTree(root)
|
||||
|
||||
// 前序走訪
|
||||
path = java.util.ArrayList<TreeNode>()
|
||||
res = java.util.ArrayList<List<TreeNode>>()
|
||||
path = mutableListOf()
|
||||
res = mutableListOf()
|
||||
preOrder(root)
|
||||
|
||||
println("\n輸出所有根節點到節點 7 的路徑")
|
||||
for (path in res as ArrayList<List<TreeNode>>) {
|
||||
val values: MutableList<Int> = ArrayList()
|
||||
for (path in res!!) {
|
||||
val _vals = mutableListOf<Int>()
|
||||
for (node in path) {
|
||||
values.add(node.value)
|
||||
_vals.add(node._val)
|
||||
}
|
||||
println(values)
|
||||
println(_vals)
|
||||
}
|
||||
}
|
||||
@@ -10,19 +10,19 @@ import utils.TreeNode
|
||||
import utils.printTree
|
||||
|
||||
var path: MutableList<TreeNode>? = null
|
||||
var res: MutableList<List<TreeNode>>? = null
|
||||
var res: MutableList<MutableList<TreeNode>>? = null
|
||||
|
||||
/* 前序走訪:例題三 */
|
||||
fun preOrder(root: TreeNode?) {
|
||||
// 剪枝
|
||||
if (root == null || root.value == 3) {
|
||||
if (root == null || root._val == 3) {
|
||||
return
|
||||
}
|
||||
// 嘗試
|
||||
path!!.add(root)
|
||||
if (root.value == 7) {
|
||||
if (root._val == 7) {
|
||||
// 記錄解
|
||||
res!!.add(ArrayList(path!!))
|
||||
res!!.add(path!!.toMutableList())
|
||||
}
|
||||
preOrder(root.left)
|
||||
preOrder(root.right)
|
||||
@@ -37,16 +37,16 @@ fun main() {
|
||||
printTree(root)
|
||||
|
||||
// 前序走訪
|
||||
path = ArrayList()
|
||||
res = ArrayList()
|
||||
path = mutableListOf()
|
||||
res = mutableListOf()
|
||||
preOrder(root)
|
||||
|
||||
println("\n輸出所有根節點到節點 7 的路徑,路徑中不包含值為 3 的節點")
|
||||
for (path in res as ArrayList<List<TreeNode>>) {
|
||||
val values: MutableList<Int> = ArrayList()
|
||||
for (path in res!!) {
|
||||
val _vals = mutableListOf<Int>()
|
||||
for (node in path) {
|
||||
values.add(node.value)
|
||||
_vals.add(node._val)
|
||||
}
|
||||
println(values)
|
||||
println(_vals)
|
||||
}
|
||||
}
|
||||
@@ -8,21 +8,20 @@ package chapter_backtracking.preorder_traversal_iii_template
|
||||
|
||||
import utils.TreeNode
|
||||
import utils.printTree
|
||||
import java.util.*
|
||||
|
||||
/* 判斷當前狀態是否為解 */
|
||||
fun isSolution(state: List<TreeNode?>): Boolean {
|
||||
return state.isNotEmpty() && state[state.size - 1]?.value == 7
|
||||
fun isSolution(state: MutableList<TreeNode?>): Boolean {
|
||||
return state.isNotEmpty() && state[state.size - 1]?._val == 7
|
||||
}
|
||||
|
||||
/* 記錄解 */
|
||||
fun recordSolution(state: MutableList<TreeNode?>?, res: MutableList<List<TreeNode?>?>) {
|
||||
res.add(state?.let { ArrayList(it) })
|
||||
fun recordSolution(state: MutableList<TreeNode?>?, res: MutableList<MutableList<TreeNode?>?>) {
|
||||
res.add(state!!.toMutableList())
|
||||
}
|
||||
|
||||
/* 判斷在當前狀態下,該選擇是否合法 */
|
||||
fun isValid(state: List<TreeNode?>?, choice: TreeNode?): Boolean {
|
||||
return choice != null && choice.value != 3
|
||||
fun isValid(state: MutableList<TreeNode?>?, choice: TreeNode?): Boolean {
|
||||
return choice != null && choice._val != 3
|
||||
}
|
||||
|
||||
/* 更新狀態 */
|
||||
@@ -38,8 +37,8 @@ fun undoChoice(state: MutableList<TreeNode?>, choice: TreeNode?) {
|
||||
/* 回溯演算法:例題三 */
|
||||
fun backtrack(
|
||||
state: MutableList<TreeNode?>,
|
||||
choices: List<TreeNode?>,
|
||||
res: MutableList<List<TreeNode?>?>
|
||||
choices: MutableList<TreeNode?>,
|
||||
res: MutableList<MutableList<TreeNode?>?>
|
||||
) {
|
||||
// 檢查是否為解
|
||||
if (isSolution(state)) {
|
||||
@@ -53,7 +52,7 @@ fun backtrack(
|
||||
// 嘗試:做出選擇,更新狀態
|
||||
makeChoice(state, choice)
|
||||
// 進行下一輪選擇
|
||||
backtrack(state, listOf(choice!!.left, choice.right), res)
|
||||
backtrack(state, mutableListOf(choice!!.left, choice.right), res)
|
||||
// 回退:撤銷選擇,恢復到之前的狀態
|
||||
undoChoice(state, choice)
|
||||
}
|
||||
@@ -67,15 +66,15 @@ fun main() {
|
||||
printTree(root)
|
||||
|
||||
// 回溯演算法
|
||||
val res: MutableList<List<TreeNode?>?> = ArrayList()
|
||||
backtrack(ArrayList(), mutableListOf(root), res)
|
||||
val res = mutableListOf<MutableList<TreeNode?>?>()
|
||||
backtrack(mutableListOf(), mutableListOf(root), res)
|
||||
|
||||
println("\n輸出所有根節點到節點 7 的路徑,要求路徑中不包含值為 3 的節點")
|
||||
for (path in res) {
|
||||
val vals = ArrayList<Int>()
|
||||
val vals = mutableListOf<Int>()
|
||||
for (node in path!!) {
|
||||
if (node != null) {
|
||||
vals.add(node.value)
|
||||
vals.add(node._val)
|
||||
}
|
||||
}
|
||||
println(vals)
|
||||
|
||||
@@ -6,19 +6,17 @@
|
||||
|
||||
package chapter_backtracking.subset_sum_i
|
||||
|
||||
import java.util.*
|
||||
|
||||
/* 回溯演算法:子集和 I */
|
||||
fun backtrack(
|
||||
state: MutableList<Int>,
|
||||
target: Int,
|
||||
choices: IntArray,
|
||||
start: Int,
|
||||
res: MutableList<List<Int>?>
|
||||
res: MutableList<MutableList<Int>?>
|
||||
) {
|
||||
// 子集和等於 target 時,記錄解
|
||||
if (target == 0) {
|
||||
res.add(ArrayList(state))
|
||||
res.add(state.toMutableList())
|
||||
return
|
||||
}
|
||||
// 走訪所有選擇
|
||||
@@ -39,11 +37,11 @@ fun backtrack(
|
||||
}
|
||||
|
||||
/* 求解子集和 I */
|
||||
fun subsetSumI(nums: IntArray, target: Int): List<List<Int>?> {
|
||||
val state: MutableList<Int> = ArrayList() // 狀態(子集)
|
||||
Arrays.sort(nums) // 對 nums 進行排序
|
||||
fun subsetSumI(nums: IntArray, target: Int): MutableList<MutableList<Int>?> {
|
||||
val state = mutableListOf<Int>() // 狀態(子集)
|
||||
nums.sort() // 對 nums 進行排序
|
||||
val start = 0 // 走訪起始點
|
||||
val res: MutableList<List<Int>?> = ArrayList() // 結果串列(子集串列)
|
||||
val res = mutableListOf<MutableList<Int>?>() // 結果串列(子集串列)
|
||||
backtrack(state, target, nums, start, res)
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -12,11 +12,11 @@ fun backtrack(
|
||||
target: Int,
|
||||
total: Int,
|
||||
choices: IntArray,
|
||||
res: MutableList<List<Int>?>
|
||||
res: MutableList<MutableList<Int>?>
|
||||
) {
|
||||
// 子集和等於 target 時,記錄解
|
||||
if (total == target) {
|
||||
res.add(ArrayList(state))
|
||||
res.add(state.toMutableList())
|
||||
return
|
||||
}
|
||||
// 走訪所有選擇
|
||||
@@ -35,10 +35,10 @@ fun backtrack(
|
||||
}
|
||||
|
||||
/* 求解子集和 I(包含重複子集) */
|
||||
fun subsetSumINaive(nums: IntArray, target: Int): List<List<Int>?> {
|
||||
val state: MutableList<Int> = ArrayList() // 狀態(子集)
|
||||
fun subsetSumINaive(nums: IntArray, target: Int): MutableList<MutableList<Int>?> {
|
||||
val state = mutableListOf<Int>() // 狀態(子集)
|
||||
val total = 0 // 子集和
|
||||
val res: MutableList<List<Int>?> = ArrayList() // 結果串列(子集串列)
|
||||
val res = mutableListOf<MutableList<Int>?>() // 結果串列(子集串列)
|
||||
backtrack(state, target, total, nums, res)
|
||||
return res
|
||||
}
|
||||
@@ -47,8 +47,7 @@ fun subsetSumINaive(nums: IntArray, target: Int): List<List<Int>?> {
|
||||
fun main() {
|
||||
val nums = intArrayOf(3, 4, 5)
|
||||
val target = 9
|
||||
|
||||
val res: List<List<Int>?> = subsetSumINaive(nums, target)
|
||||
val res = subsetSumINaive(nums, target)
|
||||
|
||||
println("輸入陣列 nums = ${nums.contentToString()}, target = $target")
|
||||
println("所有和等於 $target 的子集 res = $res")
|
||||
|
||||
@@ -6,19 +6,17 @@
|
||||
|
||||
package chapter_backtracking.subset_sum_ii
|
||||
|
||||
import java.util.*
|
||||
|
||||
/* 回溯演算法:子集和 II */
|
||||
fun backtrack(
|
||||
state: MutableList<Int>,
|
||||
target: Int,
|
||||
choices: IntArray,
|
||||
start: Int,
|
||||
res: MutableList<List<Int>?>
|
||||
res: MutableList<MutableList<Int>?>
|
||||
) {
|
||||
// 子集和等於 target 時,記錄解
|
||||
if (target == 0) {
|
||||
res.add(ArrayList(state))
|
||||
res.add(state.toMutableList())
|
||||
return
|
||||
}
|
||||
// 走訪所有選擇
|
||||
@@ -44,11 +42,11 @@ fun backtrack(
|
||||
}
|
||||
|
||||
/* 求解子集和 II */
|
||||
fun subsetSumII(nums: IntArray, target: Int): List<List<Int>?> {
|
||||
val state: MutableList<Int> = ArrayList() // 狀態(子集)
|
||||
Arrays.sort(nums) // 對 nums 進行排序
|
||||
fun subsetSumII(nums: IntArray, target: Int): MutableList<MutableList<Int>?> {
|
||||
val state = mutableListOf<Int>() // 狀態(子集)
|
||||
nums.sort() // 對 nums 進行排序
|
||||
val start = 0 // 走訪起始點
|
||||
val res: MutableList<List<Int>?> = ArrayList() // 結果串列(子集串列)
|
||||
val res = mutableListOf<MutableList<Int>?>() // 結果串列(子集串列)
|
||||
backtrack(state, target, nums, start, res)
|
||||
return res
|
||||
}
|
||||
@@ -57,7 +55,6 @@ fun subsetSumII(nums: IntArray, target: Int): List<List<Int>?> {
|
||||
fun main() {
|
||||
val nums = intArrayOf(4, 4, 5)
|
||||
val target = 9
|
||||
|
||||
val res = subsetSumII(nums, target)
|
||||
|
||||
println("輸入陣列 nums = ${nums.contentToString()}, target = $target")
|
||||
|
||||
@@ -74,4 +74,4 @@ fun main() {
|
||||
|
||||
res = fib(n)
|
||||
println("\n費波那契數列的第 $n 項為 $res")
|
||||
}
|
||||
}
|
||||
@@ -60,9 +60,9 @@ fun linearRecur(n: Int) {
|
||||
/* 平方階 */
|
||||
fun quadratic(n: Int) {
|
||||
// 矩陣佔用 O(n^2) 空間
|
||||
val numMatrix: Array<Array<Int>?> = arrayOfNulls(n)
|
||||
val numMatrix = arrayOfNulls<Array<Int>?>(n)
|
||||
// 二維串列佔用 O(n^2) 空間
|
||||
val numList: MutableList<MutableList<Int>> = arrayListOf()
|
||||
val numList = mutableListOf<MutableList<Int>>()
|
||||
for (i in 0..<n) {
|
||||
val tmp = mutableListOf<Int>()
|
||||
for (j in 0..<n) {
|
||||
@@ -104,6 +104,6 @@ fun main() {
|
||||
quadratic(n)
|
||||
quadraticRecur(n)
|
||||
// 指數階
|
||||
val root: TreeNode? = buildTree(n)
|
||||
val root = buildTree(n)
|
||||
printTree(root)
|
||||
}
|
||||
@@ -9,7 +9,7 @@ package chapter_computational_complexity.time_complexity
|
||||
/* 常數階 */
|
||||
fun constant(n: Int): Int {
|
||||
var count = 0
|
||||
val size = 10_0000
|
||||
val size = 100000
|
||||
for (i in 0..<size)
|
||||
count++
|
||||
return count
|
||||
@@ -48,7 +48,7 @@ fun quadratic(n: Int): Int {
|
||||
|
||||
/* 平方階(泡沫排序) */
|
||||
fun bubbleSort(nums: IntArray): Int {
|
||||
var count = 0
|
||||
var count = 0 // 計數器
|
||||
// 外迴圈:未排序區間為 [0, i]
|
||||
for (i in nums.size - 1 downTo 1) {
|
||||
// 內迴圈:將未排序區間 [0, i] 中的最大元素交換至該區間的最右端
|
||||
@@ -109,7 +109,7 @@ fun linearLogRecur(n: Int): Int {
|
||||
if (n <= 1)
|
||||
return 1
|
||||
var count = linearLogRecur(n / 2) + linearLogRecur(n / 2)
|
||||
for (i in 0..<n.toInt()) {
|
||||
for (i in 0..<n) {
|
||||
count++
|
||||
}
|
||||
return count
|
||||
@@ -133,7 +133,7 @@ fun main() {
|
||||
val n = 8
|
||||
println("輸入資料大小 n = $n")
|
||||
|
||||
var count: Int = constant(n)
|
||||
var count = constant(n)
|
||||
println("常數階的操作數量 = $count")
|
||||
|
||||
count = linear(n)
|
||||
@@ -144,7 +144,8 @@ fun main() {
|
||||
count = quadratic(n)
|
||||
println("平方階的操作數量 = $count")
|
||||
val nums = IntArray(n)
|
||||
for (i in 0..<n) nums[i] = n - i // [n,n-1,...,2,1]
|
||||
for (i in 0..<n)
|
||||
nums[i] = n - i // [n,n-1,...,2,1]
|
||||
count = bubbleSort(nums)
|
||||
println("平方階(泡沫排序)的操作數量 = $count")
|
||||
|
||||
|
||||
@@ -13,10 +13,9 @@ fun randomNumbers(n: Int): Array<Int?> {
|
||||
for (i in 0..<n) {
|
||||
nums[i] = i + 1
|
||||
}
|
||||
// 隨機打亂陣列元素
|
||||
val mutableList = nums.toMutableList()
|
||||
// 隨機打亂陣列元素
|
||||
mutableList.shuffle()
|
||||
// Integer[] -> int[]
|
||||
val res = arrayOfNulls<Int>(n)
|
||||
for (i in 0..<n) {
|
||||
res[i] = mutableList[i]
|
||||
@@ -39,8 +38,8 @@ fun findOne(nums: Array<Int?>): Int {
|
||||
fun main() {
|
||||
for (i in 0..9) {
|
||||
val n = 100
|
||||
val nums: Array<Int?> = randomNumbers(n)
|
||||
val index: Int = findOne(nums)
|
||||
val nums = randomNumbers(n)
|
||||
val index = findOne(nums)
|
||||
println("\n陣列 [ 1, 2, ..., n ] 被打亂後 = ${nums.contentToString()}")
|
||||
println("數字 1 的索引為 $index")
|
||||
}
|
||||
|
||||
@@ -10,7 +10,13 @@ import utils.TreeNode
|
||||
import utils.printTree
|
||||
|
||||
/* 構建二元樹:分治 */
|
||||
fun dfs(preorder: IntArray, inorderMap: Map<Int?, Int?>, i: Int, l: Int, r: Int): TreeNode? {
|
||||
fun dfs(
|
||||
preorder: IntArray,
|
||||
inorderMap: Map<Int?, Int?>,
|
||||
i: Int,
|
||||
l: Int,
|
||||
r: Int
|
||||
): TreeNode? {
|
||||
// 子樹區間為空時終止
|
||||
if (r - l < 0) return null
|
||||
// 初始化根節點
|
||||
@@ -28,7 +34,7 @@ fun dfs(preorder: IntArray, inorderMap: Map<Int?, Int?>, i: Int, l: Int, r: Int)
|
||||
/* 構建二元樹 */
|
||||
fun buildTree(preorder: IntArray, inorder: IntArray): TreeNode? {
|
||||
// 初始化雜湊表,儲存 inorder 元素到索引的對映
|
||||
val inorderMap: MutableMap<Int?, Int?> = HashMap()
|
||||
val inorderMap = HashMap<Int?, Int?>()
|
||||
for (i in inorder.indices) {
|
||||
inorderMap[inorder[i]] = i
|
||||
}
|
||||
@@ -40,8 +46,8 @@ fun buildTree(preorder: IntArray, inorder: IntArray): TreeNode? {
|
||||
fun main() {
|
||||
val preorder = intArrayOf(3, 9, 2, 1, 7)
|
||||
val inorder = intArrayOf(9, 3, 1, 2, 7)
|
||||
println("前序走訪 = " + preorder.contentToString())
|
||||
println("中序走訪 = " + inorder.contentToString())
|
||||
println("前序走訪 = ${preorder.contentToString()}")
|
||||
println("中序走訪 = ${inorder.contentToString()}")
|
||||
|
||||
val root = buildTree(preorder, inorder)
|
||||
println("構建的二元樹為:")
|
||||
|
||||
@@ -9,7 +9,7 @@ package chapter_divide_and_conquer.hanota
|
||||
/* 移動一個圓盤 */
|
||||
fun move(src: MutableList<Int>, tar: MutableList<Int>) {
|
||||
// 從 src 頂部拿出一個圓盤
|
||||
val pan: Int = src.removeAt(src.size - 1)
|
||||
val pan = src.removeAt(src.size - 1)
|
||||
// 將圓盤放入 tar 頂部
|
||||
tar.add(pan)
|
||||
}
|
||||
@@ -39,9 +39,9 @@ fun solveHanota(A: MutableList<Int>, B: MutableList<Int>, C: MutableList<Int>) {
|
||||
/* Driver Code */
|
||||
fun main() {
|
||||
// 串列尾部是柱子頂部
|
||||
val A: MutableList<Int> = ArrayList(mutableListOf(5, 4, 3, 2, 1))
|
||||
val B: MutableList<Int> = ArrayList()
|
||||
val C: MutableList<Int> = ArrayList()
|
||||
val A = mutableListOf(5, 4, 3, 2, 1)
|
||||
val B = mutableListOf<Int>()
|
||||
val C = mutableListOf<Int>()
|
||||
println("初始狀態下:")
|
||||
println("A = $A")
|
||||
println("B = $B")
|
||||
@@ -53,4 +53,4 @@ fun main() {
|
||||
println("A = $A")
|
||||
println("B = $B")
|
||||
println("C = $C")
|
||||
}
|
||||
}
|
||||
@@ -8,13 +8,14 @@ package chapter_dynamic_programming
|
||||
|
||||
/* 回溯 */
|
||||
fun backtrack(
|
||||
choices: List<Int>,
|
||||
choices: MutableList<Int>,
|
||||
state: Int,
|
||||
n: Int,
|
||||
res: MutableList<Int>
|
||||
) {
|
||||
// 當爬到第 n 階時,方案數量加 1
|
||||
if (state == n) res[0] = res[0] + 1
|
||||
if (state == n)
|
||||
res[0] = res[0] + 1
|
||||
// 走訪所有選擇
|
||||
for (choice in choices) {
|
||||
// 剪枝:不允許越過第 n 階
|
||||
@@ -29,7 +30,7 @@ fun backtrack(
|
||||
fun climbingStairsBacktrack(n: Int): Int {
|
||||
val choices = mutableListOf(1, 2) // 可選擇向上爬 1 階或 2 階
|
||||
val state = 0 // 從第 0 階開始爬
|
||||
val res = ArrayList<Int>()
|
||||
val res = mutableListOf<Int>()
|
||||
res.add(0) // 使用 res[0] 記錄方案數量
|
||||
backtrack(choices, state, n, res)
|
||||
return res[0]
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
|
||||
package chapter_dynamic_programming
|
||||
|
||||
import java.util.*
|
||||
|
||||
/* 記憶化搜尋 */
|
||||
fun dfs(i: Int, mem: IntArray): Int {
|
||||
// 已知 dp[1] 和 dp[2] ,返回之
|
||||
@@ -25,7 +23,7 @@ fun dfs(i: Int, mem: IntArray): Int {
|
||||
fun climbingStairsDFSMem(n: Int): Int {
|
||||
// mem[i] 記錄爬到第 i 階的方案總數,-1 代表無記錄
|
||||
val mem = IntArray(n + 1)
|
||||
Arrays.fill(mem, -1)
|
||||
mem.fill(-1)
|
||||
return dfs(n, mem)
|
||||
}
|
||||
|
||||
@@ -33,6 +31,6 @@ fun climbingStairsDFSMem(n: Int): Int {
|
||||
fun main() {
|
||||
val n = 9
|
||||
|
||||
val res: Int = climbingStairsDFSMem(n)
|
||||
val res = climbingStairsDFSMem(n)
|
||||
println("爬 $n 階樓梯共有 $res 種方案")
|
||||
}
|
||||
@@ -27,9 +27,7 @@ fun climbingStairsDPComp(n: Int): Int {
|
||||
var a = 1
|
||||
var b = 2
|
||||
for (i in 3..n) {
|
||||
val tmp = b
|
||||
b += a
|
||||
a = tmp
|
||||
b += a.also { a = b }
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
package chapter_dynamic_programming
|
||||
|
||||
import java.util.*
|
||||
import kotlin.math.min
|
||||
|
||||
/* 零錢兌換:動態規劃 */
|
||||
@@ -27,8 +26,7 @@ fun coinChangeDP(coins: IntArray, amt: Int): Int {
|
||||
dp[i][a] = dp[i - 1][a]
|
||||
} else {
|
||||
// 不選和選硬幣 i 這兩種方案的較小值
|
||||
dp[i][a] = min(dp[i - 1][a].toDouble(), (dp[i][a - coins[i - 1]] + 1).toDouble())
|
||||
.toInt()
|
||||
dp[i][a] = min(dp[i - 1][a], dp[i][a - coins[i - 1]] + 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,7 +39,7 @@ fun coinChangeDPComp(coins: IntArray, amt: Int): Int {
|
||||
val MAX = amt + 1
|
||||
// 初始化 dp 表
|
||||
val dp = IntArray(amt + 1)
|
||||
Arrays.fill(dp, MAX)
|
||||
dp.fill(MAX)
|
||||
dp[0] = 0
|
||||
// 狀態轉移
|
||||
for (i in 1..n) {
|
||||
@@ -51,7 +49,7 @@ fun coinChangeDPComp(coins: IntArray, amt: Int): Int {
|
||||
dp[a] = dp[a]
|
||||
} else {
|
||||
// 不選和選硬幣 i 這兩種方案的較小值
|
||||
dp[a] = min(dp[a].toDouble(), (dp[a - coins[i - 1]] + 1).toDouble()).toInt()
|
||||
dp[a] = min(dp[a], dp[a - coins[i - 1]] + 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
package chapter_dynamic_programming
|
||||
|
||||
import java.util.*
|
||||
import kotlin.math.min
|
||||
|
||||
/* 編輯距離:暴力搜尋 */
|
||||
@@ -29,7 +28,7 @@ fun editDistanceDFS(
|
||||
val delete = editDistanceDFS(s, t, i - 1, j)
|
||||
val replace = editDistanceDFS(s, t, i - 1, j - 1)
|
||||
// 返回最少編輯步數
|
||||
return (min(min(insert.toDouble(), delete.toDouble()), replace.toDouble()) + 1).toInt()
|
||||
return min(min(insert, delete), replace) + 1
|
||||
}
|
||||
|
||||
/* 編輯距離:記憶化搜尋 */
|
||||
@@ -55,7 +54,7 @@ fun editDistanceDFSMem(
|
||||
val delete = editDistanceDFSMem(s, t, mem, i - 1, j)
|
||||
val replace = editDistanceDFSMem(s, t, mem, i - 1, j - 1)
|
||||
// 記錄並返回最少編輯步數
|
||||
mem[i][j] = (min(min(insert.toDouble(), delete.toDouble()), replace.toDouble()) + 1).toInt()
|
||||
mem[i][j] = min(min(insert, delete), replace) + 1
|
||||
return mem[i][j]
|
||||
}
|
||||
|
||||
@@ -79,11 +78,7 @@ fun editDistanceDP(s: String, t: String): Int {
|
||||
dp[i][j] = dp[i - 1][j - 1]
|
||||
} else {
|
||||
// 最少編輯步數 = 插入、刪除、替換這三種操作的最少編輯步數 + 1
|
||||
dp[i][j] =
|
||||
(min(
|
||||
min(dp[i][j - 1].toDouble(), dp[i - 1][j].toDouble()),
|
||||
dp[i - 1][j - 1].toDouble()
|
||||
) + 1).toInt()
|
||||
dp[i][j] = min(min(dp[i][j - 1], dp[i - 1][j]), dp[i - 1][j - 1]) + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,7 +107,7 @@ fun editDistanceDPComp(s: String, t: String): Int {
|
||||
dp[j] = leftup
|
||||
} else {
|
||||
// 最少編輯步數 = 插入、刪除、替換這三種操作的最少編輯步數 + 1
|
||||
dp[j] = (min(min(dp[j - 1].toDouble(), dp[j].toDouble()), leftup.toDouble()) + 1).toInt()
|
||||
dp[j] = min(min(dp[j - 1], dp[j]), leftup) + 1
|
||||
}
|
||||
leftup = temp // 更新為下一輪的 dp[i-1, j-1]
|
||||
}
|
||||
@@ -133,7 +128,8 @@ fun main() {
|
||||
|
||||
// 記憶化搜尋
|
||||
val mem = Array(n + 1) { IntArray(m + 1) }
|
||||
for (row in mem) Arrays.fill(row, -1)
|
||||
for (row in mem)
|
||||
row.fill(-1)
|
||||
res = editDistanceDFSMem(s, t, mem, n, m)
|
||||
println("將 $s 更改為 $t 最少需要編輯 $res 步")
|
||||
|
||||
|
||||
@@ -6,13 +6,12 @@
|
||||
|
||||
package chapter_dynamic_programming
|
||||
|
||||
import java.util.*
|
||||
import kotlin.math.max
|
||||
|
||||
/* 0-1 背包:暴力搜尋 */
|
||||
fun knapsackDFS(
|
||||
wgt: IntArray,
|
||||
value: IntArray,
|
||||
_val: IntArray,
|
||||
i: Int,
|
||||
c: Int
|
||||
): Int {
|
||||
@@ -22,19 +21,19 @@ fun knapsackDFS(
|
||||
}
|
||||
// 若超過背包容量,則只能選擇不放入背包
|
||||
if (wgt[i - 1] > c) {
|
||||
return knapsackDFS(wgt, value, i - 1, c)
|
||||
return knapsackDFS(wgt, _val, i - 1, c)
|
||||
}
|
||||
// 計算不放入和放入物品 i 的最大價值
|
||||
val no = knapsackDFS(wgt, value, i - 1, c)
|
||||
val yes = knapsackDFS(wgt, value, i - 1, c - wgt[i - 1]) + value[i - 1]
|
||||
val no = knapsackDFS(wgt, _val, i - 1, c)
|
||||
val yes = knapsackDFS(wgt, _val, i - 1, c - wgt[i - 1]) + _val[i - 1]
|
||||
// 返回兩種方案中價值更大的那一個
|
||||
return max(no.toDouble(), yes.toDouble()).toInt()
|
||||
return max(no, yes)
|
||||
}
|
||||
|
||||
/* 0-1 背包:記憶化搜尋 */
|
||||
fun knapsackDFSMem(
|
||||
wgt: IntArray,
|
||||
value: IntArray,
|
||||
_val: IntArray,
|
||||
mem: Array<IntArray>,
|
||||
i: Int,
|
||||
c: Int
|
||||
@@ -49,20 +48,20 @@ fun knapsackDFSMem(
|
||||
}
|
||||
// 若超過背包容量,則只能選擇不放入背包
|
||||
if (wgt[i - 1] > c) {
|
||||
return knapsackDFSMem(wgt, value, mem, i - 1, c)
|
||||
return knapsackDFSMem(wgt, _val, mem, i - 1, c)
|
||||
}
|
||||
// 計算不放入和放入物品 i 的最大價值
|
||||
val no = knapsackDFSMem(wgt, value, mem, i - 1, c)
|
||||
val yes = knapsackDFSMem(wgt, value, mem, i - 1, c - wgt[i - 1]) + value[i - 1]
|
||||
val no = knapsackDFSMem(wgt, _val, mem, i - 1, c)
|
||||
val yes = knapsackDFSMem(wgt, _val, mem, i - 1, c - wgt[i - 1]) + _val[i - 1]
|
||||
// 記錄並返回兩種方案中價值更大的那一個
|
||||
mem[i][c] = max(no.toDouble(), yes.toDouble()).toInt()
|
||||
mem[i][c] = max(no, yes)
|
||||
return mem[i][c]
|
||||
}
|
||||
|
||||
/* 0-1 背包:動態規劃 */
|
||||
fun knapsackDP(
|
||||
wgt: IntArray,
|
||||
value: IntArray,
|
||||
_val: IntArray,
|
||||
cap: Int
|
||||
): Int {
|
||||
val n = wgt.size
|
||||
@@ -76,8 +75,7 @@ fun knapsackDP(
|
||||
dp[i][c] = dp[i - 1][c]
|
||||
} else {
|
||||
// 不選和選物品 i 這兩種方案的較大值
|
||||
dp[i][c] = max(dp[i - 1][c].toDouble(), (dp[i - 1][c - wgt[i - 1]] + value[i - 1]).toDouble())
|
||||
.toInt()
|
||||
dp[i][c] = max(dp[i - 1][c], dp[i - 1][c - wgt[i - 1]] + _val[i - 1])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,7 +85,7 @@ fun knapsackDP(
|
||||
/* 0-1 背包:空間最佳化後的動態規劃 */
|
||||
fun knapsackDPComp(
|
||||
wgt: IntArray,
|
||||
value: IntArray,
|
||||
_val: IntArray,
|
||||
cap: Int
|
||||
): Int {
|
||||
val n = wgt.size
|
||||
@@ -100,7 +98,7 @@ fun knapsackDPComp(
|
||||
if (wgt[i - 1] <= c) {
|
||||
// 不選和選物品 i 這兩種方案的較大值
|
||||
dp[c] =
|
||||
max(dp[c].toDouble(), (dp[c - wgt[i - 1]] + value[i - 1]).toDouble()).toInt()
|
||||
max(dp[c], dp[c - wgt[i - 1]] + _val[i - 1])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -110,27 +108,27 @@ fun knapsackDPComp(
|
||||
/* Driver Code */
|
||||
fun main() {
|
||||
val wgt = intArrayOf(10, 20, 30, 40, 50)
|
||||
val value = intArrayOf(50, 120, 150, 210, 240)
|
||||
val _val = intArrayOf(50, 120, 150, 210, 240)
|
||||
val cap = 50
|
||||
val n = wgt.size
|
||||
|
||||
// 暴力搜尋
|
||||
var res = knapsackDFS(wgt, value, n, cap)
|
||||
var res = knapsackDFS(wgt, _val, n, cap)
|
||||
println("不超過背包容量的最大物品價值為 $res")
|
||||
|
||||
// 記憶化搜尋
|
||||
val mem = Array(n + 1) { IntArray(cap + 1) }
|
||||
for (row in mem) {
|
||||
Arrays.fill(row, -1)
|
||||
row.fill(-1)
|
||||
}
|
||||
res = knapsackDFSMem(wgt, value, mem, n, cap)
|
||||
res = knapsackDFSMem(wgt, _val, mem, n, cap)
|
||||
println("不超過背包容量的最大物品價值為 $res")
|
||||
|
||||
// 動態規劃
|
||||
res = knapsackDP(wgt, value, cap)
|
||||
res = knapsackDP(wgt, _val, cap)
|
||||
println("不超過背包容量的最大物品價值為 $res")
|
||||
|
||||
// 空間最佳化後的動態規劃
|
||||
res = knapsackDPComp(wgt, value, cap)
|
||||
res = knapsackDPComp(wgt, _val, cap)
|
||||
println("不超過背包容量的最大物品價值為 $res")
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ fun minCostClimbingStairsDP(cost: IntArray): Int {
|
||||
dp[2] = cost[2]
|
||||
// 狀態轉移:從較小子問題逐步求解較大子問題
|
||||
for (i in 3..n) {
|
||||
dp[i] = (min(dp[i - 1].toDouble(), dp[i - 2].toDouble()) + cost[i]).toInt()
|
||||
dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i]
|
||||
}
|
||||
return dp[n]
|
||||
}
|
||||
@@ -32,7 +32,7 @@ fun minCostClimbingStairsDPComp(cost: IntArray): Int {
|
||||
var b = cost[2]
|
||||
for (i in 3..n) {
|
||||
val tmp = b
|
||||
b = (min(a.toDouble(), tmp.toDouble()) + cost[i]).toInt()
|
||||
b = min(a, tmp) + cost[i]
|
||||
a = tmp
|
||||
}
|
||||
return b
|
||||
|
||||
@@ -6,15 +6,10 @@
|
||||
|
||||
package chapter_dynamic_programming
|
||||
|
||||
import java.util.*
|
||||
import kotlin.math.min
|
||||
|
||||
/* 最小路徑和:暴力搜尋 */
|
||||
fun minPathSumDFS(
|
||||
grid: Array<Array<Int>>,
|
||||
i: Int,
|
||||
j: Int
|
||||
): Int {
|
||||
fun minPathSumDFS(grid: Array<IntArray>, i: Int, j: Int): Int {
|
||||
// 若為左上角單元格,則終止搜尋
|
||||
if (i == 0 && j == 0) {
|
||||
return grid[0][0]
|
||||
@@ -27,13 +22,13 @@ fun minPathSumDFS(
|
||||
val up = minPathSumDFS(grid, i - 1, j)
|
||||
val left = minPathSumDFS(grid, i, j - 1)
|
||||
// 返回從左上角到 (i, j) 的最小路徑代價
|
||||
return (min(left.toDouble(), up.toDouble()) + grid[i][j]).toInt()
|
||||
return min(left, up) + grid[i][j]
|
||||
}
|
||||
|
||||
/* 最小路徑和:記憶化搜尋 */
|
||||
fun minPathSumDFSMem(
|
||||
grid: Array<Array<Int>>,
|
||||
mem: Array<Array<Int>>,
|
||||
grid: Array<IntArray>,
|
||||
mem: Array<IntArray>,
|
||||
i: Int,
|
||||
j: Int
|
||||
): Int {
|
||||
@@ -53,12 +48,12 @@ fun minPathSumDFSMem(
|
||||
val up = minPathSumDFSMem(grid, mem, i - 1, j)
|
||||
val left = minPathSumDFSMem(grid, mem, i, j - 1)
|
||||
// 記錄並返回左上角到 (i, j) 的最小路徑代價
|
||||
mem[i][j] = (min(left.toDouble(), up.toDouble()) + grid[i][j]).toInt()
|
||||
mem[i][j] = min(left, up) + grid[i][j]
|
||||
return mem[i][j]
|
||||
}
|
||||
|
||||
/* 最小路徑和:動態規劃 */
|
||||
fun minPathSumDP(grid: Array<Array<Int>>): Int {
|
||||
fun minPathSumDP(grid: Array<IntArray>): Int {
|
||||
val n = grid.size
|
||||
val m = grid[0].size
|
||||
// 初始化 dp 表
|
||||
@@ -75,15 +70,14 @@ fun minPathSumDP(grid: Array<Array<Int>>): Int {
|
||||
// 狀態轉移:其餘行和列
|
||||
for (i in 1..<n) {
|
||||
for (j in 1..<m) {
|
||||
dp[i][j] =
|
||||
(min(dp[i][j - 1].toDouble(), dp[i - 1][j].toDouble()) + grid[i][j]).toInt()
|
||||
dp[i][j] = min(dp[i][j - 1], dp[i - 1][j]) + grid[i][j]
|
||||
}
|
||||
}
|
||||
return dp[n - 1][m - 1]
|
||||
}
|
||||
|
||||
/* 最小路徑和:空間最佳化後的動態規劃 */
|
||||
fun minPathSumDPComp(grid: Array<Array<Int>>): Int {
|
||||
fun minPathSumDPComp(grid: Array<IntArray>): Int {
|
||||
val n = grid.size
|
||||
val m = grid[0].size
|
||||
// 初始化 dp 表
|
||||
@@ -99,7 +93,7 @@ fun minPathSumDPComp(grid: Array<Array<Int>>): Int {
|
||||
dp[0] = dp[0] + grid[i][0]
|
||||
// 狀態轉移:其餘列
|
||||
for (j in 1..<m) {
|
||||
dp[j] = (min(dp[j - 1].toDouble(), dp[j].toDouble()) + grid[i][j]).toInt()
|
||||
dp[j] = min(dp[j - 1], dp[j]) + grid[i][j]
|
||||
}
|
||||
}
|
||||
return dp[m - 1]
|
||||
@@ -108,10 +102,10 @@ fun minPathSumDPComp(grid: Array<Array<Int>>): Int {
|
||||
/* Driver Code */
|
||||
fun main() {
|
||||
val grid = arrayOf(
|
||||
arrayOf(1, 3, 1, 5),
|
||||
arrayOf(2, 2, 4, 2),
|
||||
arrayOf(5, 3, 2, 1),
|
||||
arrayOf(4, 3, 5, 2)
|
||||
intArrayOf(1, 3, 1, 5),
|
||||
intArrayOf(2, 2, 4, 2),
|
||||
intArrayOf(5, 3, 2, 1),
|
||||
intArrayOf(4, 3, 5, 2)
|
||||
)
|
||||
val n = grid.size
|
||||
val m = grid[0].size
|
||||
@@ -121,9 +115,9 @@ fun main() {
|
||||
println("從左上角到右下角的最小路徑和為 $res")
|
||||
|
||||
// 記憶化搜尋
|
||||
val mem = Array(n) { Array(m) { 0 } }
|
||||
val mem = Array(n) { IntArray(m) }
|
||||
for (row in mem) {
|
||||
Arrays.fill(row, -1)
|
||||
row.fill(-1)
|
||||
}
|
||||
res = minPathSumDFSMem(grid, mem, n - 1, m - 1)
|
||||
println("從左上角到右下角的最小路徑和為 $res")
|
||||
|
||||
@@ -9,11 +9,7 @@ package chapter_dynamic_programming
|
||||
import kotlin.math.max
|
||||
|
||||
/* 完全背包:動態規劃 */
|
||||
fun unboundedKnapsackDP(
|
||||
wgt: IntArray,
|
||||
value: IntArray,
|
||||
cap: Int
|
||||
): Int {
|
||||
fun unboundedKnapsackDP(wgt: IntArray, _val: IntArray, cap: Int): Int {
|
||||
val n = wgt.size
|
||||
// 初始化 dp 表
|
||||
val dp = Array(n + 1) { IntArray(cap + 1) }
|
||||
@@ -25,8 +21,7 @@ fun unboundedKnapsackDP(
|
||||
dp[i][c] = dp[i - 1][c]
|
||||
} else {
|
||||
// 不選和選物品 i 這兩種方案的較大值
|
||||
dp[i][c] = max(dp[i - 1][c].toDouble(), (dp[i][c - wgt[i - 1]] + value[i - 1]).toDouble())
|
||||
.toInt()
|
||||
dp[i][c] = max(dp[i - 1][c], dp[i][c - wgt[i - 1]] + _val[i - 1])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,7 +31,7 @@ fun unboundedKnapsackDP(
|
||||
/* 完全背包:空間最佳化後的動態規劃 */
|
||||
fun unboundedKnapsackDPComp(
|
||||
wgt: IntArray,
|
||||
value: IntArray,
|
||||
_val: IntArray,
|
||||
cap: Int
|
||||
): Int {
|
||||
val n = wgt.size
|
||||
@@ -50,8 +45,7 @@ fun unboundedKnapsackDPComp(
|
||||
dp[c] = dp[c]
|
||||
} else {
|
||||
// 不選和選物品 i 這兩種方案的較大值
|
||||
dp[c] =
|
||||
max(dp[c].toDouble(), (dp[c - wgt[i - 1]] + value[i - 1]).toDouble()).toInt()
|
||||
dp[c] = max(dp[c], dp[c - wgt[i - 1]] + _val[i - 1])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -61,14 +55,14 @@ fun unboundedKnapsackDPComp(
|
||||
/* Driver Code */
|
||||
fun main() {
|
||||
val wgt = intArrayOf(1, 2, 3)
|
||||
val value = intArrayOf(5, 11, 15)
|
||||
val _val = intArrayOf(5, 11, 15)
|
||||
val cap = 4
|
||||
|
||||
// 動態規劃
|
||||
var res = unboundedKnapsackDP(wgt, value, cap)
|
||||
var res = unboundedKnapsackDP(wgt, _val, cap)
|
||||
println("不超過背包容量的最大物品價值為 $res")
|
||||
|
||||
// 空間最佳化後的動態規劃
|
||||
res = unboundedKnapsackDPComp(wgt, value, cap)
|
||||
res = unboundedKnapsackDPComp(wgt, _val, cap)
|
||||
println("不超過背包容量的最大物品價值為 $res")
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import utils.Vertex
|
||||
/* 基於鄰接表實現的無向圖類別 */
|
||||
class GraphAdjList(edges: Array<Array<Vertex?>>) {
|
||||
// 鄰接表,key:頂點,value:該頂點的所有鄰接頂點
|
||||
val adjList: MutableMap<Vertex, MutableList<Vertex>> = HashMap()
|
||||
val adjList = HashMap<Vertex, MutableList<Vertex>>()
|
||||
|
||||
/* 建構子 */
|
||||
init {
|
||||
@@ -70,11 +70,11 @@ class GraphAdjList(edges: Array<Array<Vertex?>>) {
|
||||
fun print() {
|
||||
println("鄰接表 =")
|
||||
for (pair in adjList.entries) {
|
||||
val tmp = ArrayList<Int>()
|
||||
val tmp = mutableListOf<Int>()
|
||||
for (vertex in pair.value) {
|
||||
tmp.add(vertex.value)
|
||||
tmp.add(vertex._val)
|
||||
}
|
||||
println("${pair.key.value}: $tmp,")
|
||||
println("${pair.key._val}: $tmp,")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,7 +82,7 @@ class GraphAdjList(edges: Array<Array<Vertex?>>) {
|
||||
/* Driver Code */
|
||||
fun main() {
|
||||
/* 初始化無向圖 */
|
||||
val v: Array<Vertex?> = Vertex.valsToVets(intArrayOf(1, 3, 2, 5, 4))
|
||||
val v = Vertex.valsToVets(intArrayOf(1, 3, 2, 5, 4))
|
||||
val edges = arrayOf(
|
||||
arrayOf(v[0], v[1]),
|
||||
arrayOf(v[0], v[3]),
|
||||
|
||||
@@ -10,8 +10,8 @@ import utils.printMatrix
|
||||
|
||||
/* 基於鄰接矩陣實現的無向圖類別 */
|
||||
class GraphAdjMat(vertices: IntArray, edges: Array<IntArray>) {
|
||||
val vertices: MutableList<Int> = ArrayList() // 頂點串列,元素代表“頂點值”,索引代表“頂點索引”
|
||||
val adjMat: MutableList<MutableList<Int>> = ArrayList() // 鄰接矩陣,行列索引對應“頂點索引”
|
||||
val vertices = mutableListOf<Int>() // 頂點串列,元素代表“頂點值”,索引代表“頂點索引”
|
||||
val adjMat = mutableListOf<MutableList<Int>>() // 鄰接矩陣,行列索引對應“頂點索引”
|
||||
|
||||
/* 建構子 */
|
||||
init {
|
||||
@@ -32,12 +32,12 @@ class GraphAdjMat(vertices: IntArray, edges: Array<IntArray>) {
|
||||
}
|
||||
|
||||
/* 新增頂點 */
|
||||
fun addVertex(value: Int) {
|
||||
fun addVertex(_val: Int) {
|
||||
val n = size()
|
||||
// 向頂點串列中新增新頂點的值
|
||||
vertices.add(value)
|
||||
vertices.add(_val)
|
||||
// 在鄰接矩陣中新增一行
|
||||
val newRow: MutableList<Int> = mutableListOf()
|
||||
val newRow = mutableListOf<Int>()
|
||||
for (j in 0..<n) {
|
||||
newRow.add(0)
|
||||
}
|
||||
@@ -50,7 +50,8 @@ class GraphAdjMat(vertices: IntArray, edges: Array<IntArray>) {
|
||||
|
||||
/* 刪除頂點 */
|
||||
fun removeVertex(index: Int) {
|
||||
if (index >= size()) throw IndexOutOfBoundsException()
|
||||
if (index >= size())
|
||||
throw IndexOutOfBoundsException()
|
||||
// 在頂點串列中移除索引 index 的頂點
|
||||
vertices.removeAt(index)
|
||||
// 在鄰接矩陣中刪除索引 index 的行
|
||||
@@ -65,7 +66,8 @@ class GraphAdjMat(vertices: IntArray, edges: Array<IntArray>) {
|
||||
// 參數 i, j 對應 vertices 元素索引
|
||||
fun addEdge(i: Int, j: Int) {
|
||||
// 索引越界與相等處理
|
||||
if (i < 0 || j < 0 || i >= size() || j >= size() || i == j) throw java.lang.IndexOutOfBoundsException()
|
||||
if (i < 0 || j < 0 || i >= size() || j >= size() || i == j)
|
||||
throw IndexOutOfBoundsException()
|
||||
// 在無向圖中,鄰接矩陣關於主對角線對稱,即滿足 (i, j) == (j, i)
|
||||
adjMat[i][j] = 1;
|
||||
adjMat[j][i] = 1;
|
||||
@@ -75,7 +77,8 @@ class GraphAdjMat(vertices: IntArray, edges: Array<IntArray>) {
|
||||
// 參數 i, j 對應 vertices 元素索引
|
||||
fun removeEdge(i: Int, j: Int) {
|
||||
// 索引越界與相等處理
|
||||
if (i < 0 || j < 0 || i >= size() || j >= size() || i == j) throw java.lang.IndexOutOfBoundsException()
|
||||
if (i < 0 || j < 0 || i >= size() || j >= size() || i == j)
|
||||
throw IndexOutOfBoundsException()
|
||||
adjMat[i][j] = 0;
|
||||
adjMat[j][i] = 0;
|
||||
}
|
||||
|
||||
@@ -11,24 +11,24 @@ import java.util.*
|
||||
|
||||
/* 廣度優先走訪 */
|
||||
// 使用鄰接表來表示圖,以便獲取指定頂點的所有鄰接頂點
|
||||
fun graphBFS(graph: GraphAdjList, startVet: Vertex): List<Vertex> {
|
||||
fun graphBFS(graph: GraphAdjList, startVet: Vertex): MutableList<Vertex?> {
|
||||
// 頂點走訪序列
|
||||
val res: MutableList<Vertex> = ArrayList()
|
||||
val res = mutableListOf<Vertex?>()
|
||||
// 雜湊表,用於記錄已被訪問過的頂點
|
||||
val visited: MutableSet<Vertex> = HashSet()
|
||||
val visited = HashSet<Vertex>()
|
||||
visited.add(startVet)
|
||||
// 佇列用於實現 BFS
|
||||
val que: Queue<Vertex> = LinkedList()
|
||||
val que = LinkedList<Vertex>()
|
||||
que.offer(startVet)
|
||||
// 以頂點 vet 為起點,迴圈直至訪問完所有頂點
|
||||
while (!que.isEmpty()) {
|
||||
val vet = que.poll() // 佇列首頂點出隊
|
||||
res.add(vet) // 記錄訪問頂點
|
||||
res.add(vet) // 記錄訪問頂點
|
||||
// 走訪該頂點的所有鄰接頂點
|
||||
for (adjVet in graph.adjList[vet]!!) {
|
||||
if (visited.contains(adjVet)) continue // 跳過已被訪問的頂點
|
||||
|
||||
que.offer(adjVet) // 只入列未訪問的頂點
|
||||
if (visited.contains(adjVet))
|
||||
continue // 跳過已被訪問的頂點
|
||||
que.offer(adjVet) // 只入列未訪問的頂點
|
||||
visited.add(adjVet) // 標記該頂點已被訪問
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,11 +15,12 @@ fun dfs(
|
||||
res: MutableList<Vertex?>,
|
||||
vet: Vertex?
|
||||
) {
|
||||
res.add(vet) // 記錄訪問頂點
|
||||
res.add(vet) // 記錄訪問頂點
|
||||
visited.add(vet) // 標記該頂點已被訪問
|
||||
// 走訪該頂點的所有鄰接頂點
|
||||
for (adjVet in graph.adjList[vet]!!) {
|
||||
if (visited.contains(adjVet)) continue // 跳過已被訪問的頂點
|
||||
if (visited.contains(adjVet))
|
||||
continue // 跳過已被訪問的頂點
|
||||
// 遞迴訪問鄰接頂點
|
||||
dfs(graph, visited, res, adjVet)
|
||||
}
|
||||
@@ -27,14 +28,11 @@ fun dfs(
|
||||
|
||||
/* 深度優先走訪 */
|
||||
// 使用鄰接表來表示圖,以便獲取指定頂點的所有鄰接頂點
|
||||
fun graphDFS(
|
||||
graph: GraphAdjList,
|
||||
startVet: Vertex?
|
||||
): List<Vertex?> {
|
||||
fun graphDFS(graph: GraphAdjList, startVet: Vertex?): MutableList<Vertex?> {
|
||||
// 頂點走訪序列
|
||||
val res: MutableList<Vertex?> = ArrayList()
|
||||
val res = mutableListOf<Vertex?>()
|
||||
// 雜湊表,用於記錄已被訪問過的頂點
|
||||
val visited: MutableSet<Vertex?> = HashSet()
|
||||
val visited = HashSet<Vertex?>()
|
||||
dfs(graph, visited, res, startVet)
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -6,34 +6,28 @@
|
||||
|
||||
package chapter_greedy
|
||||
|
||||
import java.util.*
|
||||
|
||||
/* 物品 */
|
||||
class Item(
|
||||
val w: Int, // 物品
|
||||
val v: Int // 物品價值
|
||||
val v: Int // 物品價值
|
||||
)
|
||||
|
||||
/* 分數背包:貪婪 */
|
||||
fun fractionalKnapsack(
|
||||
wgt: IntArray,
|
||||
value: IntArray,
|
||||
c: Int
|
||||
): Double {
|
||||
fun fractionalKnapsack(wgt: IntArray, _val: IntArray, c: Int): Double {
|
||||
// 建立物品串列,包含兩個屬性:重量、價值
|
||||
var cap = c
|
||||
val items = arrayOfNulls<Item>(wgt.size)
|
||||
for (i in wgt.indices) {
|
||||
items[i] = Item(wgt[i], value[i])
|
||||
items[i] = Item(wgt[i], _val[i])
|
||||
}
|
||||
// 按照單位價值 item.v / item.w 從高到低進行排序
|
||||
Arrays.sort(items, Comparator.comparingDouble { item: Item -> -(item.v.toDouble() / item.w) })
|
||||
items.sortBy { item: Item? -> -(item!!.v.toDouble() / item.w) }
|
||||
// 迴圈貪婪選擇
|
||||
var res = 0.0
|
||||
for (item in items) {
|
||||
if (item!!.w <= cap) {
|
||||
// 若剩餘容量充足,則將當前物品整個裝進背包
|
||||
res += item.v.toDouble()
|
||||
res += item.v
|
||||
cap -= item.w
|
||||
} else {
|
||||
// 若剩餘容量不足,則將當前物品的一部分裝進背包
|
||||
@@ -48,10 +42,10 @@ fun fractionalKnapsack(
|
||||
/* Driver Code */
|
||||
fun main() {
|
||||
val wgt = intArrayOf(10, 20, 30, 40, 50)
|
||||
val values = intArrayOf(50, 120, 150, 210, 240)
|
||||
val _val = intArrayOf(50, 120, 150, 210, 240)
|
||||
val cap = 50
|
||||
|
||||
// 貪婪演算法
|
||||
val res = fractionalKnapsack(wgt, values, cap)
|
||||
val res = fractionalKnapsack(wgt, _val, cap)
|
||||
println("不超過背包容量的最大物品價值為 $res")
|
||||
}
|
||||
@@ -19,8 +19,8 @@ fun maxCapacity(ht: IntArray): Int {
|
||||
// 迴圈貪婪選擇,直至兩板相遇
|
||||
while (i < j) {
|
||||
// 更新最大容量
|
||||
val cap = (min(ht[i].toDouble(), ht[j].toDouble()) * (j - i)).toInt()
|
||||
res = max(res.toDouble(), cap.toDouble()).toInt()
|
||||
val cap = min(ht[i], ht[j]) * (j - i)
|
||||
res = max(res, cap)
|
||||
// 向內移動短板
|
||||
if (ht[i] < ht[j]) {
|
||||
i++
|
||||
|
||||
@@ -19,14 +19,14 @@ fun maxProductCutting(n: Int): Int {
|
||||
val b = n % 3
|
||||
if (b == 1) {
|
||||
// 當餘數為 1 時,將一對 1 * 3 轉化為 2 * 2
|
||||
return 3.0.pow((a - 1).toDouble()).toInt() * 2 * 2
|
||||
return 3.0.pow((a - 1)).toInt() * 2 * 2
|
||||
}
|
||||
if (b == 2) {
|
||||
// 當餘數為 2 時,不做處理
|
||||
return 3.0.pow(a.toDouble()).toInt() * 2 * 2
|
||||
return 3.0.pow(a).toInt() * 2 * 2
|
||||
}
|
||||
// 當餘數為 0 時,不做處理
|
||||
return 3.0.pow(a.toDouble()).toInt()
|
||||
return 3.0.pow(a).toInt()
|
||||
}
|
||||
|
||||
/* Driver Code */
|
||||
@@ -36,4 +36,4 @@ fun main() {
|
||||
// 貪婪演算法
|
||||
val res = maxProductCutting(n)
|
||||
println("最大切分乘積為 $res")
|
||||
}
|
||||
}
|
||||
@@ -9,20 +9,14 @@ package chapter_hashing
|
||||
/* 鍵值對 */
|
||||
class Pair(
|
||||
var key: Int,
|
||||
var value: String
|
||||
var _val: String
|
||||
)
|
||||
|
||||
/* 基於陣列實現的雜湊表 */
|
||||
class ArrayHashMap {
|
||||
// 初始化陣列,包含 100 個桶
|
||||
private val buckets = arrayOfNulls<Pair>(100)
|
||||
|
||||
init {
|
||||
// 初始化陣列,包含 100 個桶
|
||||
for (i in 0..<100) {
|
||||
buckets[i] = null
|
||||
}
|
||||
}
|
||||
|
||||
/* 雜湊函式 */
|
||||
fun hashFunc(key: Int): Int {
|
||||
val index = key % 100
|
||||
@@ -33,12 +27,12 @@ class ArrayHashMap {
|
||||
fun get(key: Int): String? {
|
||||
val index = hashFunc(key)
|
||||
val pair = buckets[index] ?: return null
|
||||
return pair.value
|
||||
return pair._val
|
||||
}
|
||||
|
||||
/* 新增操作 */
|
||||
fun put(key: Int, value: String) {
|
||||
val pair = Pair(key, value)
|
||||
fun put(key: Int, _val: String) {
|
||||
val pair = Pair(key, _val)
|
||||
val index = hashFunc(key)
|
||||
buckets[index] = pair
|
||||
}
|
||||
@@ -52,27 +46,29 @@ class ArrayHashMap {
|
||||
|
||||
/* 獲取所有鍵值對 */
|
||||
fun pairSet(): MutableList<Pair> {
|
||||
val pairSet = ArrayList<Pair>()
|
||||
val pairSet = mutableListOf<Pair>()
|
||||
for (pair in buckets) {
|
||||
if (pair != null) pairSet.add(pair)
|
||||
if (pair != null)
|
||||
pairSet.add(pair)
|
||||
}
|
||||
return pairSet
|
||||
}
|
||||
|
||||
/* 獲取所有鍵 */
|
||||
fun keySet(): MutableList<Int> {
|
||||
val keySet = ArrayList<Int>()
|
||||
val keySet = mutableListOf<Int>()
|
||||
for (pair in buckets) {
|
||||
if (pair != null) keySet.add(pair.key)
|
||||
if (pair != null)
|
||||
keySet.add(pair.key)
|
||||
}
|
||||
return keySet
|
||||
}
|
||||
|
||||
/* 獲取所有值 */
|
||||
fun valueSet(): MutableList<String> {
|
||||
val valueSet = ArrayList<String>()
|
||||
val valueSet = mutableListOf<String>()
|
||||
for (pair in buckets) {
|
||||
pair?.let { valueSet.add(it.value) }
|
||||
pair?.let { valueSet.add(it._val) }
|
||||
}
|
||||
return valueSet
|
||||
}
|
||||
@@ -81,8 +77,8 @@ class ArrayHashMap {
|
||||
fun print() {
|
||||
for (kv in pairSet()) {
|
||||
val key = kv.key
|
||||
val value = kv.value
|
||||
println("${key}->${value}")
|
||||
val _val = kv._val
|
||||
println("${key} -> ${_val}")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -104,7 +100,7 @@ fun main() {
|
||||
|
||||
/* 查詢操作 */
|
||||
// 向雜湊表中輸入鍵 key ,得到值 value
|
||||
val name: String? = map.get(15937)
|
||||
val name = map.get(15937)
|
||||
println("\n輸入學號 15937 ,查詢到姓名 $name")
|
||||
|
||||
/* 刪除操作 */
|
||||
@@ -114,16 +110,16 @@ fun main() {
|
||||
map.print()
|
||||
|
||||
/* 走訪雜湊表 */
|
||||
println("\n走訪鍵值對 Key->Value")
|
||||
println("\n走訪鍵值對 Key -> Value")
|
||||
for (kv in map.pairSet()) {
|
||||
println("${kv.key} -> ${kv.value}")
|
||||
println("${kv.key} -> ${kv._val}")
|
||||
}
|
||||
println("\n單獨走訪鍵 Key")
|
||||
for (key in map.keySet()) {
|
||||
println(key)
|
||||
}
|
||||
println("\n單獨走訪值 Value")
|
||||
for (value in map.valueSet()) {
|
||||
println(value)
|
||||
for (_val in map.valueSet()) {
|
||||
println(_val)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,15 +11,15 @@ import utils.ListNode
|
||||
/* Driver Code */
|
||||
fun main() {
|
||||
val num = 3
|
||||
val hashNum = Integer.hashCode(num)
|
||||
val hashNum = num.hashCode()
|
||||
println("整數 $num 的雜湊值為 $hashNum")
|
||||
|
||||
val bol = true
|
||||
val hashBol = Boolean.hashCode()
|
||||
val hashBol = bol.hashCode()
|
||||
println("布林量 $bol 的雜湊值為 $hashBol")
|
||||
|
||||
val dec = 3.14159
|
||||
val hashDec = java.lang.Double.hashCode(dec)
|
||||
val hashDec = dec.hashCode()
|
||||
println("小數 $dec 的雜湊值為 $hashDec")
|
||||
|
||||
val str = "Hello 演算法"
|
||||
|
||||
@@ -11,7 +11,7 @@ import utils.printHashMap
|
||||
/* Driver Code */
|
||||
fun main() {
|
||||
/* 初始化雜湊表 */
|
||||
val map: MutableMap<Int, String> = HashMap()
|
||||
val map = HashMap<Int, String>()
|
||||
|
||||
/* 新增操作 */
|
||||
// 在雜湊表中新增鍵值對 (key, value)
|
||||
@@ -44,7 +44,7 @@ fun main() {
|
||||
println(key)
|
||||
}
|
||||
println("\n單獨走訪值 Value")
|
||||
for (value in map.values) {
|
||||
println(value)
|
||||
for (_val in map.values) {
|
||||
println(_val)
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ class HashMapChaining() {
|
||||
capacity = 4
|
||||
loadThres = 2.0 / 3.0
|
||||
extendRatio = 2
|
||||
buckets = ArrayList(capacity)
|
||||
buckets = mutableListOf()
|
||||
for (i in 0..<capacity) {
|
||||
buckets.add(mutableListOf())
|
||||
}
|
||||
@@ -42,14 +42,14 @@ class HashMapChaining() {
|
||||
val bucket = buckets[index]
|
||||
// 走訪桶,若找到 key ,則返回對應 val
|
||||
for (pair in bucket) {
|
||||
if (pair.key == key) return pair.value
|
||||
if (pair.key == key) return pair._val
|
||||
}
|
||||
// 若未找到 key ,則返回 null
|
||||
return null
|
||||
}
|
||||
|
||||
/* 新增操作 */
|
||||
fun put(key: Int, value: String) {
|
||||
fun put(key: Int, _val: String) {
|
||||
// 當負載因子超過閾值時,執行擴容
|
||||
if (loadFactor() > loadThres) {
|
||||
extend()
|
||||
@@ -59,12 +59,12 @@ class HashMapChaining() {
|
||||
// 走訪桶,若遇到指定 key ,則更新對應 val 並返回
|
||||
for (pair in bucket) {
|
||||
if (pair.key == key) {
|
||||
pair.value = value
|
||||
pair._val = _val
|
||||
return
|
||||
}
|
||||
}
|
||||
// 若無該 key ,則將鍵值對新增至尾部
|
||||
val pair = Pair(key, value)
|
||||
val pair = Pair(key, _val)
|
||||
bucket.add(pair)
|
||||
size++
|
||||
}
|
||||
@@ -98,7 +98,7 @@ class HashMapChaining() {
|
||||
// 將鍵值對從原雜湊表搬運至新雜湊表
|
||||
for (bucket in bucketsTmp) {
|
||||
for (pair in bucket) {
|
||||
put(pair.key, pair.value)
|
||||
put(pair.key, pair._val)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -109,7 +109,7 @@ class HashMapChaining() {
|
||||
val res = mutableListOf<String>()
|
||||
for (pair in bucket) {
|
||||
val k = pair.key
|
||||
val v = pair.value
|
||||
val v = pair._val
|
||||
res.add("$k -> $v")
|
||||
}
|
||||
println(res)
|
||||
@@ -142,4 +142,4 @@ fun main() {
|
||||
map.remove(12836)
|
||||
println("\n刪除 12836 後,雜湊表為\nKey -> Value")
|
||||
map.print()
|
||||
}
|
||||
}
|
||||
@@ -8,16 +8,21 @@ package chapter_hashing
|
||||
|
||||
/* 開放定址雜湊表 */
|
||||
class HashMapOpenAddressing {
|
||||
private var size: Int = 0 // 鍵值對數量
|
||||
private var capacity = 4 // 雜湊表容量
|
||||
private val loadThres: Double = 2.0 / 3.0 // 觸發擴容的負載因子閾值
|
||||
private val extendRatio = 2 // 擴容倍數
|
||||
private var buckets: Array<Pair?> // 桶陣列
|
||||
private val TOMBSTONE = Pair(-1, "-1") // 刪除標記
|
||||
private var size: Int // 鍵值對數量
|
||||
private var capacity: Int // 雜湊表容量
|
||||
private val loadThres: Double // 觸發擴容的負載因子閾值
|
||||
private val extendRatio: Int // 擴容倍數
|
||||
private var buckets: Array<Pair?> // 桶陣列
|
||||
private val TOMBSTONE: Pair // 刪除標記
|
||||
|
||||
/* 建構子 */
|
||||
init {
|
||||
size = 0
|
||||
capacity = 4
|
||||
loadThres = 2.0 / 3.0
|
||||
extendRatio = 2
|
||||
buckets = arrayOfNulls(capacity)
|
||||
TOMBSTONE = Pair(-1, "-1")
|
||||
}
|
||||
|
||||
/* 雜湊函式 */
|
||||
@@ -63,14 +68,14 @@ class HashMapOpenAddressing {
|
||||
val index = findBucket(key)
|
||||
// 若找到鍵值對,則返回對應 val
|
||||
if (buckets[index] != null && buckets[index] != TOMBSTONE) {
|
||||
return buckets[index]?.value
|
||||
return buckets[index]?._val
|
||||
}
|
||||
// 若鍵值對不存在,則返回 null
|
||||
return null
|
||||
}
|
||||
|
||||
/* 新增操作 */
|
||||
fun put(key: Int, value: String) {
|
||||
fun put(key: Int, _val: String) {
|
||||
// 當負載因子超過閾值時,執行擴容
|
||||
if (loadFactor() > loadThres) {
|
||||
extend()
|
||||
@@ -79,11 +84,11 @@ class HashMapOpenAddressing {
|
||||
val index = findBucket(key)
|
||||
// 若找到鍵值對,則覆蓋 val 並返回
|
||||
if (buckets[index] != null && buckets[index] != TOMBSTONE) {
|
||||
buckets[index]!!.value = value
|
||||
buckets[index]!!._val = _val
|
||||
return
|
||||
}
|
||||
// 若鍵值對不存在,則新增該鍵值對
|
||||
buckets[index] = Pair(key, value)
|
||||
buckets[index] = Pair(key, _val)
|
||||
size++
|
||||
}
|
||||
|
||||
@@ -109,7 +114,7 @@ class HashMapOpenAddressing {
|
||||
// 將鍵值對從原雜湊表搬運至新雜湊表
|
||||
for (pair in bucketsTmp) {
|
||||
if (pair != null && pair != TOMBSTONE) {
|
||||
put(pair.key, pair.value)
|
||||
put(pair.key, pair._val)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -122,7 +127,7 @@ class HashMapOpenAddressing {
|
||||
} else if (pair == TOMBSTONE) {
|
||||
println("TOMESTOME")
|
||||
} else {
|
||||
println("${pair.key} -> ${pair.value}")
|
||||
println("${pair.key} -> ${pair._val}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
package chapter_hashing
|
||||
|
||||
const val MODULUS = 10_0000_0007
|
||||
const val MODULUS = 1000000007
|
||||
|
||||
/* 加法雜湊 */
|
||||
fun addHash(key: String): Int {
|
||||
@@ -48,7 +48,7 @@ fun rotHash(key: String): Int {
|
||||
fun main() {
|
||||
val key = "Hello 演算法"
|
||||
|
||||
var hash: Int = addHash(key)
|
||||
var hash = addHash(key)
|
||||
println("加法雜湊值為 $hash")
|
||||
|
||||
hash = mulHash(key)
|
||||
|
||||
@@ -9,15 +9,15 @@ package chapter_heap
|
||||
import utils.printHeap
|
||||
import java.util.*
|
||||
|
||||
fun testPush(heap: Queue<Int>, value: Int) {
|
||||
heap.offer(value) // 元素入堆積
|
||||
print("\n元素 $value 入堆積後\n")
|
||||
fun testPush(heap: Queue<Int>, _val: Int) {
|
||||
heap.offer(_val) // 元素入堆積
|
||||
print("\n元素 $_val 入堆積後\n")
|
||||
printHeap(heap)
|
||||
}
|
||||
|
||||
fun testPop(heap: Queue<Int>) {
|
||||
val value = heap.poll() // 堆積頂元素出堆積
|
||||
print("\n堆積頂元素 $value 出堆積後\n")
|
||||
val _val = heap.poll() // 堆積頂元素出堆積
|
||||
print("\n堆積頂元素 $_val 出堆積後\n")
|
||||
printHeap(heap)
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ fun testPop(heap: Queue<Int>) {
|
||||
fun main() {
|
||||
/* 初始化堆積 */
|
||||
// 初始化小頂堆積
|
||||
val minHeap: PriorityQueue<Int>
|
||||
var minHeap = PriorityQueue<Int>()
|
||||
|
||||
// 初始化大頂堆積(使用 lambda 表示式修改 Comparator 即可)
|
||||
val maxHeap = PriorityQueue { a: Int, b: Int -> b - a }
|
||||
|
||||
@@ -10,13 +10,14 @@ import utils.printHeap
|
||||
import java.util.*
|
||||
|
||||
/* 大頂堆積 */
|
||||
class MaxHeap(nums: List<Int>?) {
|
||||
class MaxHeap(nums: MutableList<Int>?) {
|
||||
// 使用串列而非陣列,這樣無須考慮擴容問題
|
||||
// 將串列元素原封不動新增進堆積
|
||||
private val maxHeap = ArrayList(nums!!)
|
||||
private val maxHeap = mutableListOf<Int>()
|
||||
|
||||
/* 建構子,根據輸入串列建堆積 */
|
||||
init {
|
||||
// 將串列元素原封不動新增進堆積
|
||||
maxHeap.addAll(nums!!)
|
||||
// 堆積化除葉節點以外的其他所有節點
|
||||
for (i in parent(size() - 1) downTo 0) {
|
||||
siftDown(i)
|
||||
@@ -60,9 +61,9 @@ class MaxHeap(nums: List<Int>?) {
|
||||
}
|
||||
|
||||
/* 元素入堆積 */
|
||||
fun push(value: Int) {
|
||||
fun push(_val: Int) {
|
||||
// 新增節點
|
||||
maxHeap.add(value)
|
||||
maxHeap.add(_val)
|
||||
// 從底至頂堆積化
|
||||
siftUp(size() - 1)
|
||||
}
|
||||
@@ -90,11 +91,11 @@ class MaxHeap(nums: List<Int>?) {
|
||||
// 交換根節點與最右葉節點(交換首元素與尾元素)
|
||||
swap(0, size() - 1)
|
||||
// 刪除節點
|
||||
val value = maxHeap.removeAt(size() - 1)
|
||||
val _val = maxHeap.removeAt(size() - 1)
|
||||
// 從頂至底堆積化
|
||||
siftDown(0)
|
||||
// 返回堆積頂元素
|
||||
return value
|
||||
return _val
|
||||
}
|
||||
|
||||
/* 從節點 i 開始,從頂至底堆積化 */
|
||||
@@ -137,9 +138,9 @@ fun main() {
|
||||
print("\n堆積頂元素為 $peek\n")
|
||||
|
||||
/* 元素入堆積 */
|
||||
val value = 7
|
||||
maxHeap.push(value)
|
||||
print("\n元素 $value 入堆積後\n")
|
||||
val _val = 7
|
||||
maxHeap.push(_val)
|
||||
print("\n元素 $_val 入堆積後\n")
|
||||
maxHeap.print()
|
||||
|
||||
/* 堆積頂元素出堆積 */
|
||||
@@ -154,4 +155,4 @@ fun main() {
|
||||
/* 判斷堆積是否為空 */
|
||||
val isEmpty = maxHeap.isEmpty()
|
||||
print("\n堆積是否為空 $isEmpty\n")
|
||||
}
|
||||
}
|
||||
@@ -7,18 +7,17 @@
|
||||
package chapter_searching
|
||||
|
||||
import utils.ListNode
|
||||
import java.util.HashMap
|
||||
|
||||
/* 雜湊查詢(陣列) */
|
||||
fun hashingSearchArray(map: Map<Int?, Int>, target: Int): Int {
|
||||
// 雜湊表的 key: 目標元素,value: 索引
|
||||
// 雜湊表的 key: 目標元素,_val: 索引
|
||||
// 若雜湊表中無此 key ,返回 -1
|
||||
return map.getOrDefault(target, -1)
|
||||
}
|
||||
|
||||
/* 雜湊查詢(鏈結串列) */
|
||||
fun hashingSearchLinkedList(map: Map<Int?, ListNode?>, target: Int): ListNode? {
|
||||
// 雜湊表的 key: 目標節點值,value: 節點物件
|
||||
// 雜湊表的 key: 目標節點值,_val: 節點物件
|
||||
// 若雜湊表中無此 key ,返回 null
|
||||
return map.getOrDefault(target, null)
|
||||
}
|
||||
@@ -32,7 +31,7 @@ fun main() {
|
||||
// 初始化雜湊表
|
||||
val map = HashMap<Int?, Int>()
|
||||
for (i in nums.indices) {
|
||||
map[nums[i]] = i // key: 元素,value: 索引
|
||||
map[nums[i]] = i // key: 元素,_val: 索引
|
||||
}
|
||||
val index = hashingSearchArray(map, target)
|
||||
println("目標元素 3 的索引 = $index")
|
||||
@@ -42,7 +41,7 @@ fun main() {
|
||||
// 初始化雜湊表
|
||||
val map1 = HashMap<Int?, ListNode?>()
|
||||
while (head != null) {
|
||||
map1[head.value] = head // key: 節點值,value: 節點
|
||||
map1[head._val] = head // key: 節點值,_val: 節點
|
||||
head = head.next
|
||||
}
|
||||
val node = hashingSearchLinkedList(map1, target)
|
||||
|
||||
@@ -26,7 +26,7 @@ fun linearSearchLinkedList(h: ListNode?, target: Int): ListNode? {
|
||||
var head = h
|
||||
while (head != null) {
|
||||
// 找到目標節點,返回之
|
||||
if (head.value == target)
|
||||
if (head._val == target)
|
||||
return head
|
||||
head = head.next
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ fun bubbleSort(nums: IntArray) {
|
||||
for (j in 0..<i) {
|
||||
if (nums[j] > nums[j + 1]) {
|
||||
// 交換 nums[j] 與 nums[j + 1]
|
||||
nums[j] = nums[j+1].also { nums[j+1] = nums[j] }
|
||||
nums[j] = nums[j + 1].also { nums[j + 1] = nums[j] }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,15 +6,13 @@
|
||||
|
||||
package chapter_sorting
|
||||
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
/* 桶排序 */
|
||||
fun bucketSort(nums: FloatArray) {
|
||||
// 初始化 k = n/2 個桶,預期向每個桶分配 2 個元素
|
||||
val k = nums.size / 2
|
||||
val buckets = ArrayList<ArrayList<Float>>()
|
||||
val buckets = mutableListOf<MutableList<Float>>()
|
||||
for (i in 0..<k) {
|
||||
buckets.add(ArrayList())
|
||||
buckets.add(mutableListOf())
|
||||
}
|
||||
// 1. 將陣列元素分配到各個桶中
|
||||
for (num in nums) {
|
||||
|
||||
@@ -14,7 +14,7 @@ fun countingSortNaive(nums: IntArray) {
|
||||
// 1. 統計陣列最大元素 m
|
||||
var m = 0
|
||||
for (num in nums) {
|
||||
m = max(m.toDouble(), num.toDouble()).toInt()
|
||||
m = max(m, num)
|
||||
}
|
||||
// 2. 統計各數字的出現次數
|
||||
// counter[num] 代表 num 的出現次數
|
||||
@@ -40,7 +40,7 @@ fun countingSort(nums: IntArray) {
|
||||
// 1. 統計陣列最大元素 m
|
||||
var m = 0
|
||||
for (num in nums) {
|
||||
m = max(m.toDouble(), num.toDouble()).toInt()
|
||||
m = max(m, num)
|
||||
}
|
||||
// 2. 統計各數字的出現次數
|
||||
// counter[num] 代表 num 的出現次數
|
||||
|
||||
@@ -14,10 +14,13 @@ fun siftDown(nums: IntArray, n: Int, li: Int) {
|
||||
val l = 2 * i + 1
|
||||
val r = 2 * i + 2
|
||||
var ma = i
|
||||
if (l < n && nums[l] > nums[ma]) ma = l
|
||||
if (r < n && nums[r] > nums[ma]) ma = r
|
||||
if (l < n && nums[l] > nums[ma])
|
||||
ma = l
|
||||
if (r < n && nums[r] > nums[ma])
|
||||
ma = r
|
||||
// 若節點 i 最大或索引 l, r 越界,則無須繼續堆積化,跳出
|
||||
if (ma == i) break
|
||||
if (ma == i)
|
||||
break
|
||||
// 交換兩節點
|
||||
nums[i] = nums[ma].also { nums[ma] = nums[i] }
|
||||
// 迴圈向下堆積化
|
||||
|
||||
@@ -12,7 +12,7 @@ fun insertionSort(nums: IntArray) {
|
||||
for (i in nums.indices) {
|
||||
val base = nums[i]
|
||||
var j = i - 1
|
||||
// 內迴圈: 將 base 插入到已排序部分的正確位置
|
||||
// 內迴圈:將 base 插入到已排序區間 [0, i-1] 中的正確位置
|
||||
while (j >= 0 && nums[j] > base) {
|
||||
nums[j + 1] = nums[j] // 將 nums[j] 向右移動一位
|
||||
j--
|
||||
|
||||
@@ -17,8 +17,10 @@ fun merge(nums: IntArray, left: Int, mid: Int, right: Int) {
|
||||
var k = 0
|
||||
// 當左右子陣列都還有元素時,進行比較並將較小的元素複製到臨時陣列中
|
||||
while (i <= mid && j <= right) {
|
||||
if (nums[i] <= nums[j]) tmp[k++] = nums[i++]
|
||||
else tmp[k++] = nums[j++]
|
||||
if (nums[i] <= nums[j])
|
||||
tmp[k++] = nums[i++]
|
||||
else
|
||||
tmp[k++] = nums[j++]
|
||||
}
|
||||
// 將左子陣列和右子陣列的剩餘元素複製到臨時陣列中
|
||||
while (i <= mid) {
|
||||
|
||||
@@ -20,7 +20,7 @@ fun countingSortDigit(nums: IntArray, exp: Int) {
|
||||
// 統計 0~9 各數字的出現次數
|
||||
for (i in 0..<n) {
|
||||
val d = digit(nums[i], exp) // 獲取 nums[i] 第 k 位,記為 d
|
||||
counter[d]++ // 統計數字 d 的出現次數
|
||||
counter[d]++ // 統計數字 d 的出現次數
|
||||
}
|
||||
// 求前綴和,將“出現個數”轉換為“陣列索引”
|
||||
for (i in 1..9) {
|
||||
@@ -31,11 +31,12 @@ fun countingSortDigit(nums: IntArray, exp: Int) {
|
||||
for (i in n - 1 downTo 0) {
|
||||
val d = digit(nums[i], exp)
|
||||
val j = counter[d] - 1 // 獲取 d 在陣列中的索引 j
|
||||
res[j] = nums[i] // 將當前元素填入索引 j
|
||||
counter[d]-- // 將 d 的數量減 1
|
||||
res[j] = nums[i] // 將當前元素填入索引 j
|
||||
counter[d]-- // 將 d 的數量減 1
|
||||
}
|
||||
// 使用結果覆蓋原陣列 nums
|
||||
for (i in 0..<n) nums[i] = res[i]
|
||||
for (i in 0..<n)
|
||||
nums[i] = res[i]
|
||||
}
|
||||
|
||||
/* 基數排序 */
|
||||
|
||||
@@ -14,7 +14,8 @@ fun selectionSort(nums: IntArray) {
|
||||
var k = i
|
||||
// 內迴圈:找到未排序區間內的最小元素
|
||||
for (j in i + 1..<n) {
|
||||
if (nums[j] < nums[k]) k = j // 記錄最小元素的索引
|
||||
if (nums[j] < nums[k])
|
||||
k = j // 記錄最小元素的索引
|
||||
}
|
||||
// 將該最小元素與未排序區間的首個元素交換
|
||||
nums[i] = nums[k].also { nums[k] = nums[i] }
|
||||
|
||||
@@ -7,10 +7,11 @@
|
||||
package chapter_stack_and_queue
|
||||
|
||||
/* 基於環形陣列實現的雙向佇列 */
|
||||
/* 建構子 */
|
||||
class ArrayDeque(capacity: Int) {
|
||||
private var nums = IntArray(capacity) // 用於儲存雙向佇列元素的陣列
|
||||
private var front = 0 // 佇列首指標,指向佇列首元素
|
||||
private var queSize = 0 // 雙向佇列長度
|
||||
private var nums: IntArray = IntArray(capacity) // 用於儲存雙向佇列元素的陣列
|
||||
private var front: Int = 0 // 佇列首指標,指向佇列首元素
|
||||
private var queSize: Int = 0 // 雙向佇列長度
|
||||
|
||||
/* 獲取雙向佇列的容量 */
|
||||
fun capacity(): Int {
|
||||
@@ -71,7 +72,7 @@ class ArrayDeque(capacity: Int) {
|
||||
return num
|
||||
}
|
||||
|
||||
/* 訪問佇列尾元素 */
|
||||
/* 佇列尾出列 */
|
||||
fun popLast(): Int {
|
||||
val num = peekLast()
|
||||
queSize--
|
||||
|
||||
@@ -8,9 +8,9 @@ package chapter_stack_and_queue
|
||||
|
||||
/* 基於環形陣列實現的佇列 */
|
||||
class ArrayQueue(capacity: Int) {
|
||||
private val nums = IntArray(capacity) // 用於儲存佇列元素的陣列
|
||||
private var front = 0 // 佇列首指標,指向佇列首元素
|
||||
private var queSize = 0 // 佇列長度
|
||||
private val nums: IntArray = IntArray(capacity) // 用於儲存佇列元素的陣列
|
||||
private var front: Int = 0 // 佇列首指標,指向佇列首元素
|
||||
private var queSize: Int = 0 // 佇列長度
|
||||
|
||||
/* 獲取佇列的容量 */
|
||||
fun capacity(): Int {
|
||||
|
||||
@@ -9,7 +9,7 @@ package chapter_stack_and_queue
|
||||
/* 基於陣列實現的堆疊 */
|
||||
class ArrayStack {
|
||||
// 初始化串列(動態陣列)
|
||||
private val stack = ArrayList<Int>()
|
||||
private val stack = mutableListOf<Int>()
|
||||
|
||||
/* 獲取堆疊的長度 */
|
||||
fun size(): Int {
|
||||
@@ -40,7 +40,7 @@ class ArrayStack {
|
||||
|
||||
/* 將 List 轉化為 Array 並返回 */
|
||||
fun toArray(): Array<Any> {
|
||||
return stack.toArray()
|
||||
return stack.toTypedArray()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ fun main() {
|
||||
|
||||
/* 元素出堆疊 */
|
||||
val pop = stack.pop()
|
||||
println("出堆疊元素 pop = ${pop},出堆疊後 stack = ${stack.toArray().contentToString()}")
|
||||
println("出堆疊元素 pop = $pop,出堆疊後 stack = ${stack.toArray().contentToString()}")
|
||||
|
||||
/* 獲取堆疊的長度 */
|
||||
val size = stack.size()
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
package chapter_stack_and_queue
|
||||
|
||||
/* 雙向鏈結串列節點 */
|
||||
class ListNode(var value: Int) {
|
||||
class ListNode(var _val: Int) {
|
||||
// 節點值
|
||||
var next: ListNode? = null // 後繼節點引用
|
||||
var prev: ListNode? = null // 前驅節點引用
|
||||
@@ -15,9 +15,9 @@ class ListNode(var value: Int) {
|
||||
|
||||
/* 基於雙向鏈結串列實現的雙向佇列 */
|
||||
class LinkedListDeque {
|
||||
private var front: ListNode? = null // 頭節點 front ,尾節點 rear
|
||||
private var rear: ListNode? = null
|
||||
private var queSize = 0 // 雙向佇列的長度
|
||||
private var front: ListNode? = null // 頭節點 front
|
||||
private var rear: ListNode? = null // 尾節點 rear
|
||||
private var queSize: Int = 0 // 雙向佇列的長度
|
||||
|
||||
/* 獲取雙向佇列的長度 */
|
||||
fun size(): Int {
|
||||
@@ -64,12 +64,12 @@ class LinkedListDeque {
|
||||
|
||||
/* 出列操作 */
|
||||
fun pop(isFront: Boolean): Int {
|
||||
if (isEmpty()) throw IndexOutOfBoundsException()
|
||||
|
||||
val value: Int
|
||||
if (isEmpty())
|
||||
throw IndexOutOfBoundsException()
|
||||
val _val: Int
|
||||
// 佇列首出列操作
|
||||
if (isFront) {
|
||||
value = front!!.value // 暫存頭節點值
|
||||
_val = front!!._val // 暫存頭節點值
|
||||
// 刪除頭節點
|
||||
val fNext = front!!.next
|
||||
if (fNext != null) {
|
||||
@@ -79,7 +79,7 @@ class LinkedListDeque {
|
||||
front = fNext // 更新頭節點
|
||||
// 佇列尾出列操作
|
||||
} else {
|
||||
value = rear!!.value // 暫存尾節點值
|
||||
_val = rear!!._val // 暫存尾節點值
|
||||
// 刪除尾節點
|
||||
val rPrev = rear!!.prev
|
||||
if (rPrev != null) {
|
||||
@@ -89,7 +89,7 @@ class LinkedListDeque {
|
||||
rear = rPrev // 更新尾節點
|
||||
}
|
||||
queSize-- // 更新佇列長度
|
||||
return value
|
||||
return _val
|
||||
}
|
||||
|
||||
/* 佇列首出列 */
|
||||
@@ -104,17 +104,14 @@ class LinkedListDeque {
|
||||
|
||||
/* 訪問佇列首元素 */
|
||||
fun peekFirst(): Int {
|
||||
if (isEmpty()) {
|
||||
throw IndexOutOfBoundsException()
|
||||
|
||||
}
|
||||
return front!!.value
|
||||
if (isEmpty()) throw IndexOutOfBoundsException()
|
||||
return front!!._val
|
||||
}
|
||||
|
||||
/* 訪問佇列尾元素 */
|
||||
fun peekLast(): Int {
|
||||
if (isEmpty()) throw IndexOutOfBoundsException()
|
||||
return rear!!.value
|
||||
return rear!!._val
|
||||
}
|
||||
|
||||
/* 返回陣列用於列印 */
|
||||
@@ -122,7 +119,7 @@ class LinkedListDeque {
|
||||
var node = front
|
||||
val res = IntArray(size())
|
||||
for (i in res.indices) {
|
||||
res[i] = node!!.value
|
||||
res[i] = node!!._val
|
||||
node = node.next
|
||||
}
|
||||
return res
|
||||
|
||||
@@ -52,7 +52,7 @@ class LinkedListQueue(
|
||||
/* 訪問佇列首元素 */
|
||||
fun peek(): Int {
|
||||
if (isEmpty()) throw IndexOutOfBoundsException()
|
||||
return front!!.value
|
||||
return front!!._val
|
||||
}
|
||||
|
||||
/* 將鏈結串列轉化為 Array 並返回 */
|
||||
@@ -60,7 +60,7 @@ class LinkedListQueue(
|
||||
var node = front
|
||||
val res = IntArray(size())
|
||||
for (i in res.indices) {
|
||||
res[i] = node!!.value
|
||||
res[i] = node!!._val
|
||||
node = node.next
|
||||
}
|
||||
return res
|
||||
@@ -95,4 +95,4 @@ fun main() {
|
||||
/* 判斷佇列是否為空 */
|
||||
val isEmpty = queue.isEmpty()
|
||||
println("佇列是否為空 = $isEmpty")
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,7 @@ class LinkedListStack(
|
||||
/* 訪問堆疊頂元素 */
|
||||
fun peek(): Int? {
|
||||
if (isEmpty()) throw IndexOutOfBoundsException()
|
||||
return stackPeek?.value
|
||||
return stackPeek?._val
|
||||
}
|
||||
|
||||
/* 將 List 轉化為 Array 並返回 */
|
||||
@@ -49,7 +49,7 @@ class LinkedListStack(
|
||||
var node = stackPeek
|
||||
val res = IntArray(size())
|
||||
for (i in res.size - 1 downTo 0) {
|
||||
res[i] = node?.value!!
|
||||
res[i] = node?._val!!
|
||||
node = node.next
|
||||
}
|
||||
return res
|
||||
|
||||
@@ -10,14 +10,15 @@ import utils.TreeNode
|
||||
import utils.printTree
|
||||
|
||||
/* 陣列表示下的二元樹類別 */
|
||||
class ArrayBinaryTree(private val tree: List<Int?>) {
|
||||
/* 建構子 */
|
||||
class ArrayBinaryTree(private val tree: MutableList<Int?>) {
|
||||
/* 串列容量 */
|
||||
fun size(): Int {
|
||||
return tree.size
|
||||
}
|
||||
|
||||
/* 獲取索引為 i 節點的值 */
|
||||
fun value(i: Int): Int? {
|
||||
fun _val(i: Int): Int? {
|
||||
// 若索引越界,則返回 null ,代表空位
|
||||
if (i < 0 || i >= size()) return null
|
||||
return tree[i]
|
||||
@@ -39,11 +40,12 @@ class ArrayBinaryTree(private val tree: List<Int?>) {
|
||||
}
|
||||
|
||||
/* 層序走訪 */
|
||||
fun levelOrder(): List<Int?> {
|
||||
val res = ArrayList<Int?>()
|
||||
fun levelOrder(): MutableList<Int?> {
|
||||
val res = mutableListOf<Int?>()
|
||||
// 直接走訪陣列
|
||||
for (i in 0..<size()) {
|
||||
if (value(i) != null) res.add(value(i))
|
||||
if (_val(i) != null)
|
||||
res.add(_val(i))
|
||||
}
|
||||
return res
|
||||
}
|
||||
@@ -51,34 +53,38 @@ class ArrayBinaryTree(private val tree: List<Int?>) {
|
||||
/* 深度優先走訪 */
|
||||
fun dfs(i: Int, order: String, res: MutableList<Int?>) {
|
||||
// 若為空位,則返回
|
||||
if (value(i) == null) return
|
||||
if (_val(i) == null)
|
||||
return
|
||||
// 前序走訪
|
||||
if ("pre" == order) res.add(value(i))
|
||||
if ("pre" == order)
|
||||
res.add(_val(i))
|
||||
dfs(left(i), order, res)
|
||||
// 中序走訪
|
||||
if ("in" == order) res.add(value(i))
|
||||
if ("in" == order)
|
||||
res.add(_val(i))
|
||||
dfs(right(i), order, res)
|
||||
// 後序走訪
|
||||
if ("post" == order) res.add(value(i))
|
||||
if ("post" == order)
|
||||
res.add(_val(i))
|
||||
}
|
||||
|
||||
/* 前序走訪 */
|
||||
fun preOrder(): List<Int?> {
|
||||
val res = ArrayList<Int?>()
|
||||
fun preOrder(): MutableList<Int?> {
|
||||
val res = mutableListOf<Int?>()
|
||||
dfs(0, "pre", res)
|
||||
return res
|
||||
}
|
||||
|
||||
/* 中序走訪 */
|
||||
fun inOrder(): List<Int?> {
|
||||
val res = ArrayList<Int?>()
|
||||
fun inOrder(): MutableList<Int?> {
|
||||
val res = mutableListOf<Int?>()
|
||||
dfs(0, "in", res)
|
||||
return res
|
||||
}
|
||||
|
||||
/* 後序走訪 */
|
||||
fun postOrder(): List<Int?> {
|
||||
val res = ArrayList<Int?>()
|
||||
fun postOrder(): MutableList<Int?> {
|
||||
val res = mutableListOf<Int?>()
|
||||
dfs(0, "post", res)
|
||||
return res
|
||||
}
|
||||
@@ -105,10 +111,10 @@ fun main() {
|
||||
val l = abt.left(i)
|
||||
val r = abt.right(i)
|
||||
val p = abt.parent(i)
|
||||
println("當前節點的索引為 $i ,值為 ${abt.value(i)}")
|
||||
println("其左子節點的索引為 $l ,值為 ${abt.value(l)}")
|
||||
println("其右子節點的索引為 $r ,值為 ${abt.value(r)}")
|
||||
println("其父節點的索引為 $p ,值為 ${abt.value(p)}")
|
||||
println("當前節點的索引為 $i ,值為 ${abt._val(i)}")
|
||||
println("其左子節點的索引為 $l ,值為 ${abt._val(l)}")
|
||||
println("其右子節點的索引為 $r ,值為 ${abt._val(r)}")
|
||||
println("其父節點的索引為 $p ,值為 ${abt._val(p)}")
|
||||
|
||||
// 走訪樹
|
||||
var res = abt.levelOrder()
|
||||
|
||||
@@ -23,7 +23,7 @@ class AVLTree {
|
||||
/* 更新節點高度 */
|
||||
private fun updateHeight(node: TreeNode?) {
|
||||
// 節點高度等於最高子樹高度 + 1
|
||||
node?.height = (max(height(node?.left).toDouble(), height(node?.right).toDouble()) + 1).toInt()
|
||||
node?.height = max(height(node?.left), height(node?.right)) + 1
|
||||
}
|
||||
|
||||
/* 獲取平衡因子 */
|
||||
@@ -93,20 +93,22 @@ class AVLTree {
|
||||
}
|
||||
|
||||
/* 插入節點 */
|
||||
fun insert(value: Int) {
|
||||
root = insertHelper(root, value)
|
||||
fun insert(_val: Int) {
|
||||
root = insertHelper(root, _val)
|
||||
}
|
||||
|
||||
/* 遞迴插入節點(輔助方法) */
|
||||
private fun insertHelper(n: TreeNode?, value: Int): TreeNode {
|
||||
private fun insertHelper(n: TreeNode?, _val: Int): TreeNode {
|
||||
if (n == null)
|
||||
return TreeNode(value)
|
||||
return TreeNode(_val)
|
||||
var node = n
|
||||
/* 1. 查詢插入位置並插入節點 */
|
||||
if (value < node.value) node.left = insertHelper(node.left, value)
|
||||
else if (value > node.value) node.right = insertHelper(node.right, value)
|
||||
else return node // 重複節點不插入,直接返回
|
||||
|
||||
if (_val < node._val)
|
||||
node.left = insertHelper(node.left, _val)
|
||||
else if (_val > node._val)
|
||||
node.right = insertHelper(node.right, _val)
|
||||
else
|
||||
return node // 重複節點不插入,直接返回
|
||||
updateHeight(node) // 更新節點高度
|
||||
/* 2. 執行旋轉操作,使該子樹重新恢復平衡 */
|
||||
node = rotate(node)
|
||||
@@ -115,30 +117,38 @@ class AVLTree {
|
||||
}
|
||||
|
||||
/* 刪除節點 */
|
||||
fun remove(value: Int) {
|
||||
root = removeHelper(root, value)
|
||||
fun remove(_val: Int) {
|
||||
root = removeHelper(root, _val)
|
||||
}
|
||||
|
||||
/* 遞迴刪除節點(輔助方法) */
|
||||
private fun removeHelper(n: TreeNode?, value: Int): TreeNode? {
|
||||
private fun removeHelper(n: TreeNode?, _val: Int): TreeNode? {
|
||||
var node = n ?: return null
|
||||
/* 1. 查詢節點並刪除 */
|
||||
if (value < node.value) node.left = removeHelper(node.left, value)
|
||||
else if (value > node.value) node.right = removeHelper(node.right, value)
|
||||
if (_val < node._val)
|
||||
node.left = removeHelper(node.left, _val)
|
||||
else if (_val > node._val)
|
||||
node.right = removeHelper(node.right, _val)
|
||||
else {
|
||||
if (node.left == null || node.right == null) {
|
||||
val child = if (node.left != null) node.left else node.right
|
||||
val child = if (node.left != null)
|
||||
node.left
|
||||
else
|
||||
node.right
|
||||
// 子節點數量 = 0 ,直接刪除 node 並返回
|
||||
if (child == null) return null
|
||||
else node = child
|
||||
if (child == null)
|
||||
return null
|
||||
// 子節點數量 = 1 ,直接刪除 node
|
||||
else
|
||||
node = child
|
||||
} else {
|
||||
// 子節點數量 = 2 ,則將中序走訪的下個節點刪除,並用該節點替換當前節點
|
||||
var temp = node.right
|
||||
while (temp!!.left != null) {
|
||||
temp = temp.left
|
||||
}
|
||||
node.right = removeHelper(node.right, temp.value)
|
||||
node.value = temp.value
|
||||
node.right = removeHelper(node.right, temp._val)
|
||||
node._val = temp._val
|
||||
}
|
||||
}
|
||||
updateHeight(node) // 更新節點高度
|
||||
@@ -149,29 +159,34 @@ class AVLTree {
|
||||
}
|
||||
|
||||
/* 查詢節點 */
|
||||
fun search(value: Int): TreeNode? {
|
||||
fun search(_val: Int): TreeNode? {
|
||||
var cur = root
|
||||
// 迴圈查詢,越過葉節點後跳出
|
||||
while (cur != null) {
|
||||
// 目標節點在 cur 的右子樹中
|
||||
cur = if (cur.value < value) cur.right!!
|
||||
else (if (cur.value > value) cur.left
|
||||
else break)!!
|
||||
cur = if (cur._val < _val)
|
||||
cur.right!!
|
||||
// 目標節點在 cur 的左子樹中
|
||||
else if (cur._val > _val)
|
||||
cur.left
|
||||
// 找到目標節點,跳出迴圈
|
||||
else
|
||||
break
|
||||
}
|
||||
// 返回目標節點
|
||||
return cur
|
||||
}
|
||||
}
|
||||
|
||||
fun testInsert(tree: AVLTree, value: Int) {
|
||||
tree.insert(value)
|
||||
println("\n插入節點 $value 後,AVL 樹為")
|
||||
fun testInsert(tree: AVLTree, _val: Int) {
|
||||
tree.insert(_val)
|
||||
println("\n插入節點 $_val 後,AVL 樹為")
|
||||
printTree(tree.root)
|
||||
}
|
||||
|
||||
fun testRemove(tree: AVLTree, value: Int) {
|
||||
tree.remove(value)
|
||||
println("\n刪除節點 $value 後,AVL 樹為")
|
||||
fun testRemove(tree: AVLTree, _val: Int) {
|
||||
tree.remove(_val)
|
||||
println("\n刪除節點 $_val 後,AVL 樹為")
|
||||
printTree(tree.root)
|
||||
}
|
||||
|
||||
@@ -204,5 +219,5 @@ fun main() {
|
||||
|
||||
/* 查詢節點 */
|
||||
val node = avlTree.search(7)
|
||||
println("\n 查詢到的節點物件為 $node,節點值 = ${node?.value}")
|
||||
println("\n 查詢到的節點物件為 $node,節點值 = ${node?._val}")
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import utils.printTree
|
||||
|
||||
/* 二元搜尋樹 */
|
||||
class BinarySearchTree {
|
||||
// 初始化空樹
|
||||
private var root: TreeNode? = null
|
||||
|
||||
/* 獲取二元樹根節點 */
|
||||
@@ -24,11 +25,14 @@ class BinarySearchTree {
|
||||
// 迴圈查詢,越過葉節點後跳出
|
||||
while (cur != null) {
|
||||
// 目標節點在 cur 的右子樹中
|
||||
cur = if (cur.value < num) cur.right
|
||||
cur = if (cur._val < num)
|
||||
cur.right
|
||||
// 目標節點在 cur 的左子樹中
|
||||
else if (cur.value > num) cur.left
|
||||
else if (cur._val > num)
|
||||
cur.left
|
||||
// 找到目標節點,跳出迴圈
|
||||
else break
|
||||
else
|
||||
break
|
||||
}
|
||||
// 返回目標節點
|
||||
return cur
|
||||
@@ -46,45 +50,60 @@ class BinarySearchTree {
|
||||
// 迴圈查詢,越過葉節點後跳出
|
||||
while (cur != null) {
|
||||
// 找到重複節點,直接返回
|
||||
if (cur.value == num) return
|
||||
if (cur._val == num)
|
||||
return
|
||||
pre = cur
|
||||
// 插入位置在 cur 的右子樹中
|
||||
cur = if (cur.value < num) cur.right
|
||||
cur = if (cur._val < num)
|
||||
cur.right
|
||||
// 插入位置在 cur 的左子樹中
|
||||
else cur.left
|
||||
else
|
||||
cur.left
|
||||
}
|
||||
// 插入節點
|
||||
val node = TreeNode(num)
|
||||
if (pre?.value!! < num) pre.right = node
|
||||
else pre.left = node
|
||||
if (pre?._val!! < num)
|
||||
pre.right = node
|
||||
else
|
||||
pre.left = node
|
||||
}
|
||||
|
||||
/* 刪除節點 */
|
||||
fun remove(num: Int) {
|
||||
// 若樹為空,直接提前返回
|
||||
if (root == null) return
|
||||
if (root == null)
|
||||
return
|
||||
var cur = root
|
||||
var pre: TreeNode? = null
|
||||
// 迴圈查詢,越過葉節點後跳出
|
||||
while (cur != null) {
|
||||
// 找到待刪除節點,跳出迴圈
|
||||
if (cur.value == num) break
|
||||
if (cur._val == num)
|
||||
break
|
||||
pre = cur
|
||||
// 待刪除節點在 cur 的右子樹中
|
||||
cur = if (cur.value < num) cur.right
|
||||
cur = if (cur._val < num)
|
||||
cur.right
|
||||
// 待刪除節點在 cur 的左子樹中
|
||||
else cur.left
|
||||
else
|
||||
cur.left
|
||||
}
|
||||
// 若無待刪除節點,則直接返回
|
||||
if (cur == null) return
|
||||
if (cur == null)
|
||||
return
|
||||
// 子節點數量 = 0 or 1
|
||||
if (cur.left == null || cur.right == null) {
|
||||
// 當子節點數量 = 0 / 1 時, child = null / 該子節點
|
||||
val child = if (cur.left != null) cur.left else cur.right
|
||||
val child = if (cur.left != null)
|
||||
cur.left
|
||||
else
|
||||
cur.right
|
||||
// 刪除節點 cur
|
||||
if (cur != root) {
|
||||
if (pre!!.left == cur) pre.left = child
|
||||
else pre.right = child
|
||||
if (pre!!.left == cur)
|
||||
pre.left = child
|
||||
else
|
||||
pre.right = child
|
||||
} else {
|
||||
// 若刪除節點為根節點,則重新指定根節點
|
||||
root = child
|
||||
@@ -97,9 +116,9 @@ class BinarySearchTree {
|
||||
tmp = tmp.left
|
||||
}
|
||||
// 遞迴刪除節點 tmp
|
||||
remove(tmp.value)
|
||||
remove(tmp._val)
|
||||
// 用 tmp 覆蓋 cur
|
||||
cur.value = tmp.value
|
||||
cur._val = tmp._val
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -118,7 +137,7 @@ fun main() {
|
||||
|
||||
/* 查詢節點 */
|
||||
val node = bst.search(7)
|
||||
println("查詢到的節點物件為 $node,節點值 = ${node?.value}")
|
||||
println("查詢到的節點物件為 $node,節點值 = ${node?._val}")
|
||||
|
||||
/* 插入節點 */
|
||||
bst.insert(16)
|
||||
|
||||
@@ -16,13 +16,14 @@ fun levelOrder(root: TreeNode?): MutableList<Int> {
|
||||
val queue = LinkedList<TreeNode?>()
|
||||
queue.add(root)
|
||||
// 初始化一個串列,用於儲存走訪序列
|
||||
val list = ArrayList<Int>()
|
||||
while (!queue.isEmpty()) {
|
||||
val node = queue.poll() // 隊列出隊
|
||||
list.add(node?.value!!) // 儲存節點值
|
||||
if (node.left != null) queue.offer(node.left) // 左子節點入列
|
||||
|
||||
if (node.right != null) queue.offer(node.right) // 右子節點入列
|
||||
val list = mutableListOf<Int>()
|
||||
while (queue.isNotEmpty()) {
|
||||
val node = queue.poll() // 隊列出隊
|
||||
list.add(node?._val!!) // 儲存節點值
|
||||
if (node.left != null)
|
||||
queue.offer(node.left) // 左子節點入列
|
||||
if (node.right != null)
|
||||
queue.offer(node.right) // 右子節點入列
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
@@ -10,13 +10,13 @@ import utils.TreeNode
|
||||
import utils.printTree
|
||||
|
||||
// 初始化串列,用於儲存走訪序列
|
||||
var list = ArrayList<Int>()
|
||||
var list = mutableListOf<Int>()
|
||||
|
||||
/* 前序走訪 */
|
||||
fun preOrder(root: TreeNode?) {
|
||||
if (root == null) return
|
||||
// 訪問優先順序:根節點 -> 左子樹 -> 右子樹
|
||||
list.add(root.value)
|
||||
list.add(root._val)
|
||||
preOrder(root.left)
|
||||
preOrder(root.right)
|
||||
}
|
||||
@@ -26,7 +26,7 @@ fun inOrder(root: TreeNode?) {
|
||||
if (root == null) return
|
||||
// 訪問優先順序:左子樹 -> 根節點 -> 右子樹
|
||||
inOrder(root.left)
|
||||
list.add(root.value)
|
||||
list.add(root._val)
|
||||
inOrder(root.right)
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ fun postOrder(root: TreeNode?) {
|
||||
// 訪問優先順序:左子樹 -> 右子樹 -> 根節點
|
||||
postOrder(root.left)
|
||||
postOrder(root.right)
|
||||
list.add(root.value)
|
||||
list.add(root._val)
|
||||
}
|
||||
|
||||
/* Driver Code */
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
package utils
|
||||
|
||||
/* 鏈結串列節點 */
|
||||
class ListNode(var value: Int) {
|
||||
class ListNode(var _val: Int) {
|
||||
var next: ListNode? = null
|
||||
|
||||
companion object {
|
||||
@@ -15,11 +15,11 @@ class ListNode(var value: Int) {
|
||||
fun arrToLinkedList(arr: IntArray): ListNode? {
|
||||
val dum = ListNode(0)
|
||||
var head = dum
|
||||
for (value in arr) {
|
||||
head.next = ListNode(value)
|
||||
for (_val in arr) {
|
||||
head.next = ListNode(_val)
|
||||
head = head.next!!
|
||||
}
|
||||
return dum.next
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ fun <T> printMatrix(matrix: Array<Array<T>>) {
|
||||
}
|
||||
|
||||
/* 列印矩陣(List) */
|
||||
fun <T> printMatrix(matrix: List<List<T>>) {
|
||||
fun <T> printMatrix(matrix: MutableList<MutableList<T>>) {
|
||||
println("[")
|
||||
for (row in matrix) {
|
||||
println(" $row,")
|
||||
@@ -31,9 +31,9 @@ fun <T> printMatrix(matrix: List<List<T>>) {
|
||||
/* 列印鏈結串列 */
|
||||
fun printLinkedList(h: ListNode?) {
|
||||
var head = h
|
||||
val list = ArrayList<String>()
|
||||
val list = mutableListOf<String>()
|
||||
while (head != null) {
|
||||
list.add(head.value.toString())
|
||||
list.add(head._val.toString())
|
||||
head = head.next
|
||||
}
|
||||
println(list.joinToString(separator = " -> "))
|
||||
@@ -70,7 +70,7 @@ fun printTree(root: TreeNode?, prev: Trunk?, isRight: Boolean) {
|
||||
}
|
||||
|
||||
showTrunks(trunk)
|
||||
println(" ${root.value}")
|
||||
println(" ${root._val}")
|
||||
|
||||
if (prev != null) {
|
||||
prev.str = prevStr
|
||||
@@ -91,16 +91,17 @@ fun showTrunks(p: Trunk?) {
|
||||
/* 列印雜湊表 */
|
||||
fun <K, V> printHashMap(map: Map<K, V>) {
|
||||
for ((key, value) in map) {
|
||||
println(key.toString() + " -> " + value)
|
||||
println("${key.toString()} -> $value")
|
||||
}
|
||||
}
|
||||
|
||||
/* 列印堆積 */
|
||||
fun printHeap(queue: Queue<Int>?) {
|
||||
val list = queue?.let { ArrayList(it) }
|
||||
val list = mutableListOf<Int?>()
|
||||
queue?.let { list.addAll(it) }
|
||||
print("堆積的陣列表示:")
|
||||
println(list)
|
||||
println("堆積的樹狀表示:")
|
||||
val root = list?.let { TreeNode.listToTree(it) }
|
||||
val root = TreeNode.listToTree(list)
|
||||
printTree(root)
|
||||
}
|
||||
}
|
||||
@@ -7,8 +7,9 @@
|
||||
package utils
|
||||
|
||||
/* 二元樹節點類別 */
|
||||
/* 建構子 */
|
||||
class TreeNode(
|
||||
var value: Int // 節點值
|
||||
var _val: Int // 節點值
|
||||
) {
|
||||
var height: Int = 0 // 節點高度
|
||||
var left: TreeNode? = null // 左子節點引用
|
||||
@@ -53,14 +54,14 @@ class TreeNode(
|
||||
while (i >= res.size) {
|
||||
res.add(null)
|
||||
}
|
||||
res[i] = root.value
|
||||
res[i] = root._val
|
||||
treeToListDFS(root.left, 2 * i + 1, res)
|
||||
treeToListDFS(root.right, 2 * i + 2, res)
|
||||
}
|
||||
|
||||
/* 將二元樹序列化為串列 */
|
||||
fun treeToList(root: TreeNode?): List<Int?> {
|
||||
val res = ArrayList<Int?>()
|
||||
fun treeToList(root: TreeNode?): MutableList<Int?> {
|
||||
val res = mutableListOf<Int?>()
|
||||
treeToListDFS(root, 0, res)
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
package utils
|
||||
|
||||
/* 頂點類別 */
|
||||
class Vertex(val value: Int) {
|
||||
class Vertex(val _val: Int) {
|
||||
companion object {
|
||||
/* 輸入值串列 vals ,返回頂點串列 vets */
|
||||
fun valsToVets(vals: IntArray): Array<Vertex?> {
|
||||
@@ -19,10 +19,10 @@ class Vertex(val value: Int) {
|
||||
}
|
||||
|
||||
/* 輸入頂點串列 vets ,返回值串列 vals */
|
||||
fun vetsToVals(vets: List<Vertex?>): List<Int> {
|
||||
val vals = ArrayList<Int>()
|
||||
fun vetsToVals(vets: MutableList<Vertex?>): MutableList<Int> {
|
||||
val vals = mutableListOf<Int>()
|
||||
for (vet in vets) {
|
||||
vals.add(vet!!.value)
|
||||
vals.add(vet!!._val)
|
||||
}
|
||||
return vals
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user