Re-translate the Japanese version (#1871)

* Retranslate Japanese docs with GPT-5.4

* Retranslate Japanese code with GPT-5.4
This commit is contained in:
Yudong Jin
2026-03-30 07:30:15 +08:00
committed by GitHub
parent fe6443235b
commit d7b2277d2b
1444 changed files with 83312 additions and 8363 deletions
+130
View File
@@ -0,0 +1,130 @@
# Created by https://www.toptal.com/developers/gitignore/api/objective-c,swift,swiftpackagemanager
# Edit at https://www.toptal.com/developers/gitignore?templates=objective-c,swift,swiftpackagemanager
### Objective-C ###
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## User settings
xcuserdata/
## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
*.xcscmblueprint
*.xccheckout
## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
build/
DerivedData/
*.moved-aside
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
## Obj-C/Swift specific
*.hmap
## App packaging
*.ipa
*.dSYM.zip
*.dSYM
# CocoaPods
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
# Pods/
# Add this line if you want to avoid checking in source code from the Xcode workspace
# *.xcworkspace
# Carthage
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
Carthage/Build/
# fastlane
# It is recommended to not store the screenshots in the git repo.
# Instead, use fastlane to re-generate the screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://docs.fastlane.tools/best-practices/source-control/#source-control
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots/**/*.png
fastlane/test_output
# Code Injection
# After new code Injection tools there's a generated folder /iOSInjectionProject
# https://github.com/johnno1962/injectionforxcode
iOSInjectionProject/
### Objective-C Patch ###
### Swift ###
# Xcode
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## Playgrounds
timeline.xctimeline
playground.xcworkspace
# Swift Package Manager
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
# Packages/
# Package.pins
# Package.resolved
# *.xcodeproj
# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
# hence it is not needed unless you have added a package configuration file to your project
# .swiftpm
.build/
# CocoaPods
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
# Pods/
# Add this line if you want to avoid checking in source code from the Xcode workspace
# *.xcworkspace
# Carthage
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
# Accio dependency management
Dependencies/
.accio/
# fastlane
# It is recommended to not store the screenshots in the git repo.
# Instead, use fastlane to re-generate the screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://docs.fastlane.tools/best-practices/source-control/#source-control
# Code Injection
# After new code Injection tools there's a generated folder /iOSInjectionProject
# https://github.com/johnno1962/injectionforxcode
### SwiftPackageManager ###
Packages
xcuserdata
*.xcodeproj
# End of https://www.toptal.com/developers/gitignore/api/objective-c,swift,swiftpackagemanager
+14
View File
@@ -0,0 +1,14 @@
{
"pins" : [
{
"identity" : "swift-collections",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-collections",
"state" : {
"branch" : "release/1.1",
"revision" : "4a1d92ba85027010d2c528c05576cde9a362254b"
}
}
],
"version" : 2
}
+206
View File
@@ -0,0 +1,206 @@
// swift-tools-version: 5.7
import PackageDescription
let package = Package(
name: "HelloAlgo",
products: [
// chapter_computational_complexity
.executable(name: "iteration", targets: ["iteration"]),
.executable(name: "recursion", targets: ["recursion"]),
.executable(name: "time_complexity", targets: ["time_complexity"]),
.executable(name: "worst_best_time_complexity", targets: ["worst_best_time_complexity"]),
.executable(name: "space_complexity", targets: ["space_complexity"]),
// chapter_array_and_linkedlist
.executable(name: "array", targets: ["array"]),
.executable(name: "linked_list", targets: ["linked_list"]),
.executable(name: "list", targets: ["list"]),
.executable(name: "my_list", targets: ["my_list"]),
// chapter_stack_and_queue
.executable(name: "stack", targets: ["stack"]),
.executable(name: "linkedlist_stack", targets: ["linkedlist_stack"]),
.executable(name: "array_stack", targets: ["array_stack"]),
.executable(name: "queue", targets: ["queue"]),
.executable(name: "linkedlist_queue", targets: ["linkedlist_queue"]),
.executable(name: "array_queue", targets: ["array_queue"]),
.executable(name: "deque", targets: ["deque"]),
.executable(name: "linkedlist_deque", targets: ["linkedlist_deque"]),
.executable(name: "array_deque", targets: ["array_deque"]),
// chapter_hashing
.executable(name: "hash_map", targets: ["hash_map"]),
.executable(name: "array_hash_map", targets: ["array_hash_map"]),
.executable(name: "hash_map_chaining", targets: ["hash_map_chaining"]),
.executable(name: "hash_map_open_addressing", targets: ["hash_map_open_addressing"]),
.executable(name: "simple_hash", targets: ["simple_hash"]),
.executable(name: "built_in_hash", targets: ["built_in_hash"]),
// chapter_tree
.executable(name: "binary_tree", targets: ["binary_tree"]),
.executable(name: "binary_tree_bfs", targets: ["binary_tree_bfs"]),
.executable(name: "binary_tree_dfs", targets: ["binary_tree_dfs"]),
.executable(name: "array_binary_tree", targets: ["array_binary_tree"]),
.executable(name: "binary_search_tree", targets: ["binary_search_tree"]),
.executable(name: "avl_tree", targets: ["avl_tree"]),
// chapter_heap
.executable(name: "heap", targets: ["heap"]),
.executable(name: "my_heap", targets: ["my_heap"]),
.executable(name: "top_k", targets: ["top_k"]),
// chapter_graph
.executable(name: "graph_adjacency_matrix", targets: ["graph_adjacency_matrix"]),
.executable(name: "graph_adjacency_list", targets: ["graph_adjacency_list"]),
.executable(name: "graph_bfs", targets: ["graph_bfs"]),
.executable(name: "graph_dfs", targets: ["graph_dfs"]),
// chapter_searching
.executable(name: "binary_search", targets: ["binary_search"]),
.executable(name: "binary_search_insertion", targets: ["binary_search_insertion"]),
.executable(name: "binary_search_edge", targets: ["binary_search_edge"]),
.executable(name: "two_sum", targets: ["two_sum"]),
.executable(name: "linear_search", targets: ["linear_search"]),
.executable(name: "hashing_search", targets: ["hashing_search"]),
// chapter_sorting
.executable(name: "selection_sort", targets: ["selection_sort"]),
.executable(name: "bubble_sort", targets: ["bubble_sort"]),
.executable(name: "insertion_sort", targets: ["insertion_sort"]),
.executable(name: "quick_sort", targets: ["quick_sort"]),
.executable(name: "merge_sort", targets: ["merge_sort"]),
.executable(name: "heap_sort", targets: ["heap_sort"]),
.executable(name: "bucket_sort", targets: ["bucket_sort"]),
.executable(name: "counting_sort", targets: ["counting_sort"]),
.executable(name: "radix_sort", targets: ["radix_sort"]),
// chapter_divide_and_conquer
.executable(name: "binary_search_recur", targets: ["binary_search_recur"]),
.executable(name: "build_tree", targets: ["build_tree"]),
.executable(name: "hanota", targets: ["hanota"]),
// chapter_backtracking
.executable(name: "preorder_traversal_i_compact", targets: ["preorder_traversal_i_compact"]),
.executable(name: "preorder_traversal_ii_compact", targets: ["preorder_traversal_ii_compact"]),
.executable(name: "preorder_traversal_iii_compact", targets: ["preorder_traversal_iii_compact"]),
.executable(name: "preorder_traversal_iii_template", targets: ["preorder_traversal_iii_template"]),
.executable(name: "permutations_i", targets: ["permutations_i"]),
.executable(name: "permutations_ii", targets: ["permutations_ii"]),
.executable(name: "subset_sum_i_naive", targets: ["subset_sum_i_naive"]),
.executable(name: "subset_sum_i", targets: ["subset_sum_i"]),
.executable(name: "subset_sum_ii", targets: ["subset_sum_ii"]),
.executable(name: "n_queens", targets: ["n_queens"]),
// chapter_dynamic_programming
.executable(name: "climbing_stairs_backtrack", targets: ["climbing_stairs_backtrack"]),
.executable(name: "climbing_stairs_dfs", targets: ["climbing_stairs_dfs"]),
.executable(name: "climbing_stairs_dfs_mem", targets: ["climbing_stairs_dfs_mem"]),
.executable(name: "climbing_stairs_dp", targets: ["climbing_stairs_dp"]),
.executable(name: "min_cost_climbing_stairs_dp", targets: ["min_cost_climbing_stairs_dp"]),
.executable(name: "climbing_stairs_constraint_dp", targets: ["climbing_stairs_constraint_dp"]),
.executable(name: "min_path_sum", targets: ["min_path_sum"]),
.executable(name: "knapsack", targets: ["knapsack"]),
.executable(name: "unbounded_knapsack", targets: ["unbounded_knapsack"]),
.executable(name: "coin_change", targets: ["coin_change"]),
.executable(name: "coin_change_ii", targets: ["coin_change_ii"]),
.executable(name: "edit_distance", targets: ["edit_distance"]),
// chapter_greedy
.executable(name: "coin_change_greedy", targets: ["coin_change_greedy"]),
.executable(name: "fractional_knapsack", targets: ["fractional_knapsack"]),
.executable(name: "max_capacity", targets: ["max_capacity"]),
.executable(name: "max_product_cutting", targets: ["max_product_cutting"]),
],
dependencies: [
.package(url: "https://github.com/apple/swift-collections", branch: "release/1.1"),
],
targets: [
// helper
.target(name: "utils", path: "utils"),
.target(name: "graph_adjacency_list_target", dependencies: ["utils"], path: "chapter_graph", sources: ["graph_adjacency_list_target.swift"], swiftSettings: [.define("TARGET")]),
.target(name: "binary_search_insertion_target", path: "chapter_searching", sources: ["binary_search_insertion_target.swift"], swiftSettings: [.define("TARGET")]),
// chapter_computational_complexity
.executableTarget(name: "iteration", path: "chapter_computational_complexity", sources: ["iteration.swift"]),
.executableTarget(name: "recursion", path: "chapter_computational_complexity", sources: ["recursion.swift"]),
.executableTarget(name: "time_complexity", path: "chapter_computational_complexity", sources: ["time_complexity.swift"]),
.executableTarget(name: "worst_best_time_complexity", path: "chapter_computational_complexity", sources: ["worst_best_time_complexity.swift"]),
.executableTarget(name: "space_complexity", dependencies: ["utils"], path: "chapter_computational_complexity", sources: ["space_complexity.swift"]),
// chapter_array_and_linkedlist
.executableTarget(name: "array", path: "chapter_array_and_linkedlist", sources: ["array.swift"]),
.executableTarget(name: "linked_list", dependencies: ["utils"], path: "chapter_array_and_linkedlist", sources: ["linked_list.swift"]),
.executableTarget(name: "list", path: "chapter_array_and_linkedlist", sources: ["list.swift"]),
.executableTarget(name: "my_list", path: "chapter_array_and_linkedlist", sources: ["my_list.swift"]),
// chapter_stack_and_queue
.executableTarget(name: "stack", path: "chapter_stack_and_queue", sources: ["stack.swift"]),
.executableTarget(name: "linkedlist_stack", dependencies: ["utils"], path: "chapter_stack_and_queue", sources: ["linkedlist_stack.swift"]),
.executableTarget(name: "array_stack", path: "chapter_stack_and_queue", sources: ["array_stack.swift"]),
.executableTarget(name: "queue", path: "chapter_stack_and_queue", sources: ["queue.swift"]),
.executableTarget(name: "linkedlist_queue", dependencies: ["utils"], path: "chapter_stack_and_queue", sources: ["linkedlist_queue.swift"]),
.executableTarget(name: "array_queue", path: "chapter_stack_and_queue", sources: ["array_queue.swift"]),
.executableTarget(name: "deque", path: "chapter_stack_and_queue", sources: ["deque.swift"]),
.executableTarget(name: "linkedlist_deque", path: "chapter_stack_and_queue", sources: ["linkedlist_deque.swift"]),
.executableTarget(name: "array_deque", path: "chapter_stack_and_queue", sources: ["array_deque.swift"]),
// chapter_hashing
.executableTarget(name: "hash_map", dependencies: ["utils"], path: "chapter_hashing", sources: ["hash_map.swift"]),
.executableTarget(name: "array_hash_map", dependencies: ["utils"], path: "chapter_hashing", sources: ["array_hash_map.swift"]),
.executableTarget(name: "hash_map_chaining", dependencies: ["utils"], path: "chapter_hashing", sources: ["hash_map_chaining.swift"]),
.executableTarget(name: "hash_map_open_addressing", dependencies: ["utils"], path: "chapter_hashing", sources: ["hash_map_open_addressing.swift"]),
.executableTarget(name: "simple_hash", path: "chapter_hashing", sources: ["simple_hash.swift"]),
.executableTarget(name: "built_in_hash", dependencies: ["utils"], path: "chapter_hashing", sources: ["built_in_hash.swift"]),
// chapter_tree
.executableTarget(name: "binary_tree", dependencies: ["utils"], path: "chapter_tree", sources: ["binary_tree.swift"]),
.executableTarget(name: "binary_tree_bfs", dependencies: ["utils"], path: "chapter_tree", sources: ["binary_tree_bfs.swift"]),
.executableTarget(name: "binary_tree_dfs", dependencies: ["utils"], path: "chapter_tree", sources: ["binary_tree_dfs.swift"]),
.executableTarget(name: "array_binary_tree", dependencies: ["utils"], path: "chapter_tree", sources: ["array_binary_tree.swift"]),
.executableTarget(name: "binary_search_tree", dependencies: ["utils"], path: "chapter_tree", sources: ["binary_search_tree.swift"]),
.executableTarget(name: "avl_tree", dependencies: ["utils"], path: "chapter_tree", sources: ["avl_tree.swift"]),
// chapter_heap
.executableTarget(name: "heap", dependencies: ["utils", .product(name: "HeapModule", package: "swift-collections")], path: "chapter_heap", sources: ["heap.swift"]),
.executableTarget(name: "my_heap", dependencies: ["utils"], path: "chapter_heap", sources: ["my_heap.swift"]),
.executableTarget(name: "top_k", dependencies: ["utils", .product(name: "HeapModule", package: "swift-collections")], path: "chapter_heap", sources: ["top_k.swift"]),
// chapter_graph
.executableTarget(name: "graph_adjacency_matrix", dependencies: ["utils"], path: "chapter_graph", sources: ["graph_adjacency_matrix.swift"]),
.executableTarget(name: "graph_adjacency_list", dependencies: ["utils"], path: "chapter_graph", sources: ["graph_adjacency_list.swift"]),
.executableTarget(name: "graph_bfs", dependencies: ["utils", "graph_adjacency_list_target"], path: "chapter_graph", sources: ["graph_bfs.swift"]),
.executableTarget(name: "graph_dfs", dependencies: ["utils", "graph_adjacency_list_target"], path: "chapter_graph", sources: ["graph_dfs.swift"]),
// chapter_searching
.executableTarget(name: "binary_search", path: "chapter_searching", sources: ["binary_search.swift"]),
.executableTarget(name: "binary_search_insertion", path: "chapter_searching", sources: ["binary_search_insertion.swift"]),
.executableTarget(name: "binary_search_edge", dependencies: ["binary_search_insertion_target"], path: "chapter_searching", sources: ["binary_search_edge.swift"]),
.executableTarget(name: "two_sum", path: "chapter_searching", sources: ["two_sum.swift"]),
.executableTarget(name: "linear_search", dependencies: ["utils"], path: "chapter_searching", sources: ["linear_search.swift"]),
.executableTarget(name: "hashing_search", dependencies: ["utils"], path: "chapter_searching", sources: ["hashing_search.swift"]),
// chapter_sorting
.executableTarget(name: "selection_sort", path: "chapter_sorting", sources: ["selection_sort.swift"]),
.executableTarget(name: "bubble_sort", path: "chapter_sorting", sources: ["bubble_sort.swift"]),
.executableTarget(name: "insertion_sort", path: "chapter_sorting", sources: ["insertion_sort.swift"]),
.executableTarget(name: "quick_sort", path: "chapter_sorting", sources: ["quick_sort.swift"]),
.executableTarget(name: "merge_sort", path: "chapter_sorting", sources: ["merge_sort.swift"]),
.executableTarget(name: "heap_sort", path: "chapter_sorting", sources: ["heap_sort.swift"]),
.executableTarget(name: "bucket_sort", path: "chapter_sorting", sources: ["bucket_sort.swift"]),
.executableTarget(name: "counting_sort", path: "chapter_sorting", sources: ["counting_sort.swift"]),
.executableTarget(name: "radix_sort", path: "chapter_sorting", sources: ["radix_sort.swift"]),
// chapter_divide_and_conquer
.executableTarget(name: "binary_search_recur", path: "chapter_divide_and_conquer", sources: ["binary_search_recur.swift"]),
.executableTarget(name: "build_tree", dependencies: ["utils"], path: "chapter_divide_and_conquer", sources: ["build_tree.swift"]),
.executableTarget(name: "hanota", path: "chapter_divide_and_conquer", sources: ["hanota.swift"]),
// chapter_backtracking
.executableTarget(name: "preorder_traversal_i_compact", dependencies: ["utils"], path: "chapter_backtracking", sources: ["preorder_traversal_i_compact.swift"]),
.executableTarget(name: "preorder_traversal_ii_compact", dependencies: ["utils"], path: "chapter_backtracking", sources: ["preorder_traversal_ii_compact.swift"]),
.executableTarget(name: "preorder_traversal_iii_compact", dependencies: ["utils"], path: "chapter_backtracking", sources: ["preorder_traversal_iii_compact.swift"]),
.executableTarget(name: "preorder_traversal_iii_template", dependencies: ["utils"], path: "chapter_backtracking", sources: ["preorder_traversal_iii_template.swift"]),
.executableTarget(name: "permutations_i", path: "chapter_backtracking", sources: ["permutations_i.swift"]),
.executableTarget(name: "permutations_ii", path: "chapter_backtracking", sources: ["permutations_ii.swift"]),
.executableTarget(name: "subset_sum_i_naive", path: "chapter_backtracking", sources: ["subset_sum_i_naive.swift"]),
.executableTarget(name: "subset_sum_i", path: "chapter_backtracking", sources: ["subset_sum_i.swift"]),
.executableTarget(name: "subset_sum_ii", path: "chapter_backtracking", sources: ["subset_sum_ii.swift"]),
.executableTarget(name: "n_queens", path: "chapter_backtracking", sources: ["n_queens.swift"]),
// chapter_dynamic_programming
.executableTarget(name: "climbing_stairs_backtrack", path: "chapter_dynamic_programming", sources: ["climbing_stairs_backtrack.swift"]),
.executableTarget(name: "climbing_stairs_dfs", path: "chapter_dynamic_programming", sources: ["climbing_stairs_dfs.swift"]),
.executableTarget(name: "climbing_stairs_dfs_mem", path: "chapter_dynamic_programming", sources: ["climbing_stairs_dfs_mem.swift"]),
.executableTarget(name: "climbing_stairs_dp", path: "chapter_dynamic_programming", sources: ["climbing_stairs_dp.swift"]),
.executableTarget(name: "min_cost_climbing_stairs_dp", path: "chapter_dynamic_programming", sources: ["min_cost_climbing_stairs_dp.swift"]),
.executableTarget(name: "climbing_stairs_constraint_dp", path: "chapter_dynamic_programming", sources: ["climbing_stairs_constraint_dp.swift"]),
.executableTarget(name: "min_path_sum", path: "chapter_dynamic_programming", sources: ["min_path_sum.swift"]),
.executableTarget(name: "knapsack", path: "chapter_dynamic_programming", sources: ["knapsack.swift"]),
.executableTarget(name: "unbounded_knapsack", path: "chapter_dynamic_programming", sources: ["unbounded_knapsack.swift"]),
.executableTarget(name: "coin_change", path: "chapter_dynamic_programming", sources: ["coin_change.swift"]),
.executableTarget(name: "coin_change_ii", path: "chapter_dynamic_programming", sources: ["coin_change_ii.swift"]),
.executableTarget(name: "edit_distance", path: "chapter_dynamic_programming", sources: ["edit_distance.swift"]),
// chapter_greedy
.executableTarget(name: "coin_change_greedy", path: "chapter_greedy", sources: ["coin_change_greedy.swift"]),
.executableTarget(name: "fractional_knapsack", path: "chapter_greedy", sources: ["fractional_knapsack.swift"]),
.executableTarget(name: "max_capacity", path: "chapter_greedy", sources: ["max_capacity.swift"]),
.executableTarget(name: "max_product_cutting", path: "chapter_greedy", sources: ["max_product_cutting.swift"]),
]
)
@@ -0,0 +1,107 @@
/**
* File: array.swift
* Created Time: 2023-01-05
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
func randomAccess(nums: [Int]) -> Int {
// [0, nums.count) 1
let randomIndex = nums.indices.randomElement()!
//
let randomNum = nums[randomIndex]
return randomNum
}
/* */
func extend(nums: [Int], enlarge: Int) -> [Int] {
//
var res = Array(repeating: 0, count: nums.count + enlarge)
//
for i in nums.indices {
res[i] = nums[i]
}
//
return res
}
/* index num */
func insert(nums: inout [Int], num: Int, index: Int) {
// index 1
for i in nums.indices.dropFirst(index).reversed() {
nums[i] = nums[i - 1]
}
// index num
nums[index] = num
}
/* index */
func remove(nums: inout [Int], index: Int) {
// index 1
for i in nums.indices.dropFirst(index).dropLast() {
nums[i] = nums[i + 1]
}
}
/* */
func traverse(nums: [Int]) {
var count = 0
//
for i in nums.indices {
count += nums[i]
}
//
for num in nums {
count += num
}
//
for (i, num) in nums.enumerated() {
count += nums[i]
count += num
}
}
/* */
func find(nums: [Int], target: Int) -> Int {
for i in nums.indices {
if nums[i] == target {
return i
}
}
return -1
}
@main
enum _Array {
/* Driver Code */
static func main() {
/* */
let arr = Array(repeating: 0, count: 5)
print("配列 arr = \(arr)")
var nums = [1, 3, 2, 5, 4]
print("配列 nums = \(nums)")
/* */
let randomNum = randomAccess(nums: nums)
print("nums からランダムな要素を取得 \(randomNum)")
/* */
nums = extend(nums: nums, enlarge: 3)
print("配列の長さを 8 に拡張すると、nums = \(nums)")
/* */
insert(nums: &nums, num: 6, index: 3)
print("インデックス 3 に数値 6 を挿入すると、nums = \(nums)")
/* */
remove(nums: &nums, index: 2)
print("インデックス 2 の要素を削除すると、nums = \(nums)")
/* */
traverse(nums: nums)
/* */
let index = find(nums: nums, target: 3)
print("nums 内で要素 3 を検索すると、インデックス = \(index)")
}
}
@@ -0,0 +1,90 @@
/**
* File: linked_list.swift
* Created Time: 2023-01-08
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
/* n0 P */
func insert(n0: ListNode, P: ListNode) {
let n1 = n0.next
P.next = n1
n0.next = P
}
/* n0 */
func remove(n0: ListNode) {
if n0.next == nil {
return
}
// n0 -> P -> n1
let P = n0.next
let n1 = P?.next
n0.next = n1
}
/* index */
func access(head: ListNode, index: Int) -> ListNode? {
var head: ListNode? = head
for _ in 0 ..< index {
if head == nil {
return nil
}
head = head?.next
}
return head
}
/* target */
func find(head: ListNode, target: Int) -> Int {
var head: ListNode? = head
var index = 0
while head != nil {
if head?.val == target {
return index
}
head = head?.next
index += 1
}
return -1
}
@main
enum LinkedList {
/* Driver Code */
static func main() {
/* */
//
let n0 = ListNode(x: 1)
let n1 = ListNode(x: 3)
let n2 = ListNode(x: 2)
let n3 = ListNode(x: 5)
let n4 = ListNode(x: 4)
//
n0.next = n1
n1.next = n2
n2.next = n3
n3.next = n4
print("初期化した連結リストは")
PrintUtil.printLinkedList(head: n0)
/* */
insert(n0: n0, P: ListNode(x: 0))
print("ノード挿入後の連結リストは")
PrintUtil.printLinkedList(head: n0)
/* */
remove(n0: n0)
print("ノード削除後の連結リストは")
PrintUtil.printLinkedList(head: n0)
/* */
let node = access(head: n0, index: 3)
print("連結リストのインデックス 3 にあるノードの値 = \(node!.val)")
/* */
let index = find(head: n0, target: 2)
print("連結リスト内で値が 2 のノードのインデックス = \(index)")
}
}
@@ -0,0 +1,63 @@
/**
* File: list.swift
* Created Time: 2023-01-08
* Author: nuomi1 (nuomi1@qq.com)
*/
@main
enum List {
/* Driver Code */
static func main() {
/* */
var nums = [1, 3, 2, 5, 4]
print("リスト nums = \(nums)")
/* */
let num = nums[1]
print("インデックス 1 の要素にアクセスすると、num = \(num)")
/* */
nums[1] = 0
print("インデックス 1 の要素を 0 に更新すると、nums = \(nums)")
/* */
nums.removeAll()
print("リストを空にした後、nums = \(nums)")
/* */
nums.append(1)
nums.append(3)
nums.append(2)
nums.append(5)
nums.append(4)
print("要素追加後、nums = \(nums)")
/* */
nums.insert(6, at: 3)
print("インデックス 3 に数値 6 を挿入すると、nums = \(nums)")
/* */
nums.remove(at: 3)
print("インデックス 3 の要素を削除すると、nums = \(nums)")
/* */
var count = 0
for i in nums.indices {
count += nums[i]
}
/* */
count = 0
for x in nums {
count += x
}
/* 2 */
let nums1 = [6, 8, 7, 10, 9]
nums.append(contentsOf: nums1)
print("リスト nums1 を nums の後ろに連結すると、nums = \(nums)")
/* */
nums.sort()
print("リストをソートした後、nums = \(nums)")
}
}
@@ -0,0 +1,146 @@
/**
* File: my_list.swift
* Created Time: 2023-01-08
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
class MyList {
private var arr: [Int] //
private var _capacity: Int //
private var _size: Int //
private let extendRatio: Int //
/* */
init() {
_capacity = 10
_size = 0
extendRatio = 2
arr = Array(repeating: 0, count: _capacity)
}
/* */
func size() -> Int {
_size
}
/* */
func capacity() -> Int {
_capacity
}
/* */
func get(index: Int) -> Int {
//
if index < 0 || index >= size() {
fatalError("インデックスが範囲外")
}
return arr[index]
}
/* */
func set(index: Int, num: Int) {
if index < 0 || index >= size() {
fatalError("インデックスが範囲外")
}
arr[index] = num
}
/* */
func add(num: Int) {
//
if size() == capacity() {
extendCapacity()
}
arr[size()] = num
//
_size += 1
}
/* */
func insert(index: Int, num: Int) {
if index < 0 || index >= size() {
fatalError("インデックスが範囲外")
}
//
if size() == capacity() {
extendCapacity()
}
// index 1
for j in (index ..< size()).reversed() {
arr[j + 1] = arr[j]
}
arr[index] = num
//
_size += 1
}
/* */
@discardableResult
func remove(index: Int) -> Int {
if index < 0 || index >= size() {
fatalError("インデックスが範囲外")
}
let num = arr[index]
// index 1
for j in index ..< (size() - 1) {
arr[j] = arr[j + 1]
}
//
_size -= 1
//
return num
}
/* */
func extendCapacity() {
// extendRatio
arr = arr + Array(repeating: 0, count: capacity() * (extendRatio - 1))
//
_capacity = arr.count
}
/* */
func toArray() -> [Int] {
Array(arr.prefix(size()))
}
}
@main
enum _MyList {
/* Driver Code */
static func main() {
/* */
let nums = MyList()
/* */
nums.add(num: 1)
nums.add(num: 3)
nums.add(num: 2)
nums.add(num: 5)
nums.add(num: 4)
print("リスト nums = \(nums.toArray()) 、容量 = \(nums.capacity()) 、長さ = \(nums.size())")
/* */
nums.insert(index: 3, num: 6)
print("インデックス 3 に数値 6 を挿入すると、nums = \(nums.toArray())")
/* */
nums.remove(index: 3)
print("インデックス 3 の要素を削除すると、nums = \(nums.toArray())")
/* */
let num = nums.get(index: 1)
print("インデックス 1 の要素にアクセスすると、num = \(num)")
/* */
nums.set(index: 1, num: 0)
print("インデックス 1 の要素を 0 に更新すると、nums = \(nums.toArray())")
/* */
for i in 0 ..< 10 {
// i = 5
nums.add(num: i)
}
print("拡張後のリスト nums = \(nums.toArray()) 、容量 = \(nums.capacity()) 、長さ = \(nums.size())")
}
}
@@ -0,0 +1,67 @@
/**
* File: n_queens.swift
* Created Time: 2023-05-14
* Author: nuomi1 (nuomi1@qq.com)
*/
/* N */
func backtrack(row: Int, n: Int, state: inout [[String]], res: inout [[[String]]], cols: inout [Bool], diags1: inout [Bool], diags2: inout [Bool]) {
//
if row == n {
res.append(state)
return
}
//
for col in 0 ..< n {
//
let diag1 = row - col + n - 1
let diag2 = row + col
//
if !cols[col] && !diags1[diag1] && !diags2[diag2] {
//
state[row][col] = "Q"
cols[col] = true
diags1[diag1] = true
diags2[diag2] = true
//
backtrack(row: row + 1, n: n, state: &state, res: &res, cols: &cols, diags1: &diags1, diags2: &diags2)
//
state[row][col] = "#"
cols[col] = false
diags1[diag1] = false
diags2[diag2] = false
}
}
}
/* N */
func nQueens(n: Int) -> [[[String]]] {
// n*n 'Q' '#'
var state = Array(repeating: Array(repeating: "#", count: n), count: n)
var cols = Array(repeating: false, count: n) //
var diags1 = Array(repeating: false, count: 2 * n - 1) //
var diags2 = Array(repeating: false, count: 2 * n - 1) //
var res: [[[String]]] = []
backtrack(row: 0, n: n, state: &state, res: &res, cols: &cols, diags1: &diags1, diags2: &diags2)
return res
}
@main
enum NQueens {
/* Driver Code */
static func main() {
let n = 4
let res = nQueens(n: n)
print("入力された盤面の縦横は \(n)")
print("クイーンの配置方法は全部で \(res.count) 通り")
for state in res {
print("--------------------")
for row in state {
print(row)
}
}
}
}
@@ -0,0 +1,50 @@
/**
* File: permutations_i.swift
* Created Time: 2023-04-30
* Author: nuomi1 (nuomi1@qq.com)
*/
/* I */
func backtrack(state: inout [Int], choices: [Int], selected: inout [Bool], res: inout [[Int]]) {
//
if state.count == choices.count {
res.append(state)
return
}
//
for (i, choice) in choices.enumerated() {
//
if !selected[i] {
// :
selected[i] = true
state.append(choice)
//
backtrack(state: &state, choices: choices, selected: &selected, res: &res)
//
selected[i] = false
state.removeLast()
}
}
}
/* I */
func permutationsI(nums: [Int]) -> [[Int]] {
var state: [Int] = []
var selected = Array(repeating: false, count: nums.count)
var res: [[Int]] = []
backtrack(state: &state, choices: nums, selected: &selected, res: &res)
return res
}
@main
enum PermutationsI {
/* Driver Code */
static func main() {
let nums = [1, 2, 3]
let res = permutationsI(nums: nums)
print("入力配列 nums = \(nums)")
print("すべての順列 res = \(res)")
}
}
@@ -0,0 +1,52 @@
/**
* File: permutations_ii.swift
* Created Time: 2023-04-30
* Author: nuomi1 (nuomi1@qq.com)
*/
/* II */
func backtrack(state: inout [Int], choices: [Int], selected: inout [Bool], res: inout [[Int]]) {
//
if state.count == choices.count {
res.append(state)
return
}
//
var duplicated: Set<Int> = []
for (i, choice) in choices.enumerated() {
//
if !selected[i], !duplicated.contains(choice) {
// :
duplicated.insert(choice) //
selected[i] = true
state.append(choice)
//
backtrack(state: &state, choices: choices, selected: &selected, res: &res)
//
selected[i] = false
state.removeLast()
}
}
}
/* II */
func permutationsII(nums: [Int]) -> [[Int]] {
var state: [Int] = []
var selected = Array(repeating: false, count: nums.count)
var res: [[Int]] = []
backtrack(state: &state, choices: nums, selected: &selected, res: &res)
return res
}
@main
enum PermutationsII {
/* Driver Code */
static func main() {
let nums = [1, 2, 3]
let res = permutationsII(nums: nums)
print("入力配列 nums = \(nums)")
print("すべての順列 res = \(res)")
}
}
@@ -0,0 +1,43 @@
/**
* File: preorder_traversal_i_compact.swift
* Created Time: 2023-04-30
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
var res: [TreeNode] = []
/* 1 */
func preOrder(root: TreeNode?) {
guard let root = root else {
return
}
if root.val == 7 {
//
res.append(root)
}
preOrder(root: root.left)
preOrder(root: root.right)
}
@main
enum PreorderTraversalICompact {
/* Driver Code */
static func main() {
let root = TreeNode.listToTree(arr: [1, 7, 3, 4, 5, 6, 7])
print("\n二分木を初期化")
PrintUtil.printTree(root: root)
//
res = []
preOrder(root: root)
print("\n値が 7 のすべてのノードを出力")
var vals: [Int] = []
for node in res {
vals.append(node.val)
}
print(vals)
}
}
@@ -0,0 +1,51 @@
/**
* File: preorder_traversal_ii_compact.swift
* Created Time: 2023-04-30
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
var path: [TreeNode] = []
var res: [[TreeNode]] = []
/* 2 */
func preOrder(root: TreeNode?) {
guard let root = root else {
return
}
//
path.append(root)
if root.val == 7 {
//
res.append(path)
}
preOrder(root: root.left)
preOrder(root: root.right)
//
path.removeLast()
}
@main
enum PreorderTraversalIICompact {
/* Driver Code */
static func main() {
let root = TreeNode.listToTree(arr: [1, 7, 3, 4, 5, 6, 7])
print("\n二分木を初期化")
PrintUtil.printTree(root: root)
//
path = []
res = []
preOrder(root: root)
print("\n根ノードからノード 7 までのすべての経路を出力")
for path in res {
var vals: [Int] = []
for node in path {
vals.append(node.val)
}
print(vals)
}
}
}
@@ -0,0 +1,52 @@
/**
* File: preorder_traversal_iii_compact.swift
* Created Time: 2023-04-30
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
var path: [TreeNode] = []
var res: [[TreeNode]] = []
/* 3 */
func preOrder(root: TreeNode?) {
//
guard let root = root, root.val != 3 else {
return
}
//
path.append(root)
if root.val == 7 {
//
res.append(path)
}
preOrder(root: root.left)
preOrder(root: root.right)
//
path.removeLast()
}
@main
enum PreorderTraversalIIICompact {
/* Driver Code */
static func main() {
let root = TreeNode.listToTree(arr: [1, 7, 3, 4, 5, 6, 7])
print("\n二分木を初期化")
PrintUtil.printTree(root: root)
//
path = []
res = []
preOrder(root: root)
print("\n根ノードからノード 7 までのすべての経路を出力し、経路に値が 3 のノードを含まない")
for path in res {
var vals: [Int] = []
for node in path {
vals.append(node.val)
}
print(vals)
}
}
}
@@ -0,0 +1,76 @@
/**
* File: preorder_traversal_iii_template.swift
* Created Time: 2023-04-30
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
/* */
func isSolution(state: [TreeNode]) -> Bool {
!state.isEmpty && state.last!.val == 7
}
/* */
func recordSolution(state: [TreeNode], res: inout [[TreeNode]]) {
res.append(state)
}
/* */
func isValid(state: [TreeNode], choice: TreeNode?) -> Bool {
choice != nil && choice!.val != 3
}
/* */
func makeChoice(state: inout [TreeNode], choice: TreeNode) {
state.append(choice)
}
/* */
func undoChoice(state: inout [TreeNode], choice: TreeNode) {
state.removeLast()
}
/* 3 */
func backtrack(state: inout [TreeNode], choices: [TreeNode], res: inout [[TreeNode]]) {
//
if isSolution(state: state) {
recordSolution(state: state, res: &res)
}
//
for choice in choices {
//
if isValid(state: state, choice: choice) {
// :
makeChoice(state: &state, choice: choice)
//
backtrack(state: &state, choices: [choice.left, choice.right].compactMap { $0 }, res: &res)
//
undoChoice(state: &state, choice: choice)
}
}
}
@main
enum PreorderTraversalIIITemplate {
/* Driver Code */
static func main() {
let root = TreeNode.listToTree(arr: [1, 7, 3, 4, 5, 6, 7])
print("\n二分木を初期化")
PrintUtil.printTree(root: root)
//
var state: [TreeNode] = []
var res: [[TreeNode]] = []
backtrack(state: &state, choices: [root].compactMap { $0 }, res: &res)
print("\n根ノードからノード 7 までのすべての経路を出力し、経路に値が 3 のノードを含まない")
for path in res {
var vals: [Int] = []
for node in path {
vals.append(node.val)
}
print(vals)
}
}
}
@@ -0,0 +1,53 @@
/**
* File: subset_sum_i.swift
* Created Time: 2023-07-02
* Author: nuomi1 (nuomi1@qq.com)
*/
/* I */
func backtrack(state: inout [Int], target: Int, choices: [Int], start: Int, res: inout [[Int]]) {
// target
if target == 0 {
res.append(state)
return
}
//
// 2: start
for i in choices.indices.dropFirst(start) {
// 1 target
// target
if target - choices[i] < 0 {
break
}
// target start
state.append(choices[i])
//
backtrack(state: &state, target: target - choices[i], choices: choices, start: i, res: &res)
//
state.removeLast()
}
}
/* I */
func subsetSumI(nums: [Int], target: Int) -> [[Int]] {
var state: [Int] = [] //
let nums = nums.sorted() // nums
let start = 0 //
var res: [[Int]] = [] //
backtrack(state: &state, target: target, choices: nums, start: start, res: &res)
return res
}
@main
enum SubsetSumI {
/* Driver Code */
static func main() {
let nums = [3, 4, 5]
let target = 9
let res = subsetSumI(nums: nums, target: target)
print("入力配列 nums = \(nums), target = \(target)")
print("和が \(target) に等しいすべての部分集合 res = \(res)")
}
}
@@ -0,0 +1,51 @@
/**
* File: subset_sum_i_naive.swift
* Created Time: 2023-07-02
* Author: nuomi1 (nuomi1@qq.com)
*/
/* I */
func backtrack(state: inout [Int], target: Int, total: Int, choices: [Int], res: inout [[Int]]) {
// target
if total == target {
res.append(state)
return
}
//
for i in choices.indices {
// target
if total + choices[i] > target {
continue
}
// total
state.append(choices[i])
//
backtrack(state: &state, target: target, total: total + choices[i], choices: choices, res: &res)
//
state.removeLast()
}
}
/* I */
func subsetSumINaive(nums: [Int], target: Int) -> [[Int]] {
var state: [Int] = [] //
let total = 0 //
var res: [[Int]] = [] //
backtrack(state: &state, target: target, total: total, choices: nums, res: &res)
return res
}
@main
enum SubsetSumINaive {
/* Driver Code */
static func main() {
let nums = [3, 4, 5]
let target = 9
let res = subsetSumINaive(nums: nums, target: target)
print("入力配列 nums = \(nums), target = \(target)")
print("和が \(target) に等しいすべての部分集合 res = \(res)")
print("この方法の出力結果には重複した集合が含まれることに注意してください")
}
}
@@ -0,0 +1,58 @@
/**
* File: subset_sum_ii.swift
* Created Time: 2023-07-02
* Author: nuomi1 (nuomi1@qq.com)
*/
/* II */
func backtrack(state: inout [Int], target: Int, choices: [Int], start: Int, res: inout [[Int]]) {
// target
if target == 0 {
res.append(state)
return
}
//
// 2: start
// 3: start
for i in choices.indices.dropFirst(start) {
// 1 target
// target
if target - choices[i] < 0 {
break
}
// 4
if i > start, choices[i] == choices[i - 1] {
continue
}
// target start
state.append(choices[i])
//
backtrack(state: &state, target: target - choices[i], choices: choices, start: i + 1, res: &res)
//
state.removeLast()
}
}
/* II */
func subsetSumII(nums: [Int], target: Int) -> [[Int]] {
var state: [Int] = [] //
let nums = nums.sorted() // nums
let start = 0 //
var res: [[Int]] = [] //
backtrack(state: &state, target: target, choices: nums, start: start, res: &res)
return res
}
@main
enum SubsetSumII {
/* Driver Code */
static func main() {
let nums = [4, 4, 5]
let target = 9
let res = subsetSumII(nums: nums, target: target)
print("入力配列 nums = \(nums), target = \(target)")
print("和が \(target) に等しいすべての部分集合 res = \(res)")
}
}
@@ -0,0 +1,75 @@
/**
* File: iteration.swift
* Created Time: 2023-09-02
* Author: nuomi1 (nuomi1@qq.com)
*/
/* for */
func forLoop(n: Int) -> Int {
var res = 0
// 1, 2, ..., n-1, n
for i in 1 ... n {
res += i
}
return res
}
/* while */
func whileLoop(n: Int) -> Int {
var res = 0
var i = 1 //
// 1, 2, ..., n-1, n
while i <= n {
res += i
i += 1 //
}
return res
}
/* while 2 */
func whileLoopII(n: Int) -> Int {
var res = 0
var i = 1 //
// 1, 4, 10, ...
while i <= n {
res += i
//
i += 1
i *= 2
}
return res
}
/* for */
func nestedForLoop(n: Int) -> String {
var res = ""
// i = 1, 2, ..., n-1, n
for i in 1 ... n {
// j = 1, 2, ..., n-1, n
for j in 1 ... n {
res.append("(\(i), \(j)), ")
}
}
return res
}
@main
enum Iteration {
/* Driver Code */
static func main() {
let n = 5
var res = 0
res = forLoop(n: n)
print("\nfor ループの合計結果 res = \(res)")
res = whileLoop(n: n)
print("\nwhile ループの合計結果 res = \(res)")
res = whileLoopII(n: n)
print("\nwhile ループ(2 回更新)の合計結果 res = \(res)")
let resStr = nestedForLoop(n: n)
print("\n二重 for ループの走査結果 \(resStr)")
}
}
@@ -0,0 +1,79 @@
/**
* File: recursion.swift
* Created Time: 2023-09-02
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
func recur(n: Int) -> Int {
//
if n == 1 {
return 1
}
//
let res = recur(n: n - 1)
//
return n + res
}
/* */
func forLoopRecur(n: Int) -> Int {
// 使
var stack: [Int] = []
var res = 0
//
for i in (1 ... n).reversed() {
//
stack.append(i)
}
//
while !stack.isEmpty {
//
res += stack.removeLast()
}
// res = 1+2+3+...+n
return res
}
/* */
func tailRecur(n: Int, res: Int) -> Int {
//
if n == 0 {
return res
}
//
return tailRecur(n: n - 1, res: res + n)
}
/* */
func fib(n: Int) -> Int {
// f(1) = 0, f(2) = 1
if n == 1 || n == 2 {
return n - 1
}
// f(n) = f(n-1) + f(n-2)
let res = fib(n: n - 1) + fib(n: n - 2)
// f(n)
return res
}
@main
enum Recursion {
/* Driver Code */
static func main() {
let n = 5
var res = 0
res = recursion.recur(n: n)
print("\n再帰関数による総和結果 res = \(res)")
res = recursion.forLoopRecur(n: n)
print("\n反復で再帰をシミュレートした総和結果 res = \(res)")
res = recursion.tailRecur(n: n, res: 0)
print("\n末尾再帰関数による総和結果 res = \(res)")
res = recursion.fib(n: n)
print("\nフィボナッチ数列の第 \(n) 項は \(res)")
}
}
@@ -0,0 +1,98 @@
/**
* File: space_complexity.swift
* Created Time: 2023-01-01
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
/* */
@discardableResult
func function() -> Int {
//
return 0
}
/* */
func constant(n: Int) {
// O(1)
let a = 0
var b = 0
let nums = Array(repeating: 0, count: 10000)
let node = ListNode(x: 0)
// O(1)
for _ in 0 ..< n {
let c = 0
}
// O(1)
for _ in 0 ..< n {
function()
}
}
/* */
func linear(n: Int) {
// n O(n) 使
let nums = Array(repeating: 0, count: n)
// n O(n) 使
let nodes = (0 ..< n).map { ListNode(x: $0) }
// n O(n) 使
let map = Dictionary(uniqueKeysWithValues: (0 ..< n).map { ($0, "\($0)") })
}
/* */
func linearRecur(n: Int) {
print("再帰 n = \(n)")
if n == 1 {
return
}
linearRecur(n: n - 1)
}
/* */
func quadratic(n: Int) {
// O(n^2) 使
let numList = Array(repeating: Array(repeating: 0, count: n), count: n)
}
/* */
@discardableResult
func quadraticRecur(n: Int) -> Int {
if n <= 0 {
return 0
}
// nums n, n-1, ..., 2, 1
let nums = Array(repeating: 0, count: n)
print("再帰 n = \(n) における nums の長さ = \(nums.count)")
return quadraticRecur(n: n - 1)
}
/* */
func buildTree(n: Int) -> TreeNode? {
if n == 0 {
return nil
}
let root = TreeNode(x: 0)
root.left = buildTree(n: n - 1)
root.right = buildTree(n: n - 1)
return root
}
@main
enum SpaceComplexity {
/* Driver Code */
static func main() {
let n = 5
//
constant(n: n)
//
linear(n: n)
linearRecur(n: n)
//
quadratic(n: n)
quadraticRecur(n: n)
//
let root = buildTree(n: n)
PrintUtil.printTree(root: root)
}
}
@@ -0,0 +1,172 @@
/**
* File: time_complexity.swift
* Created Time: 2022-12-26
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
func constant(n: Int) -> Int {
var count = 0
let size = 100_000
for _ in 0 ..< size {
count += 1
}
return count
}
/* */
func linear(n: Int) -> Int {
var count = 0
for _ in 0 ..< n {
count += 1
}
return count
}
/* */
func arrayTraversal(nums: [Int]) -> Int {
var count = 0
//
for _ in nums {
count += 1
}
return count
}
/* */
func quadratic(n: Int) -> Int {
var count = 0
// n
for _ in 0 ..< n {
for _ in 0 ..< n {
count += 1
}
}
return count
}
/* */
func bubbleSort(nums: inout [Int]) -> Int {
var count = 0 //
// [0, i]
for i in nums.indices.dropFirst().reversed() {
// [0, i]
for j in 0 ..< i {
if nums[j] > nums[j + 1] {
// nums[j] nums[j + 1]
let tmp = nums[j]
nums[j] = nums[j + 1]
nums[j + 1] = tmp
count += 3 // 3
}
}
}
return count
}
/* */
func exponential(n: Int) -> Int {
var count = 0
var base = 1
// 2 1, 2, 4, 8, ..., 2^(n-1)
for _ in 0 ..< n {
for _ in 0 ..< base {
count += 1
}
base *= 2
}
// count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1
return count
}
/* */
func expRecur(n: Int) -> Int {
if n == 1 {
return 1
}
return expRecur(n: n - 1) + expRecur(n: n - 1) + 1
}
/* */
func logarithmic(n: Int) -> Int {
var count = 0
var n = n
while n > 1 {
n = n / 2
count += 1
}
return count
}
/* */
func logRecur(n: Int) -> Int {
if n <= 1 {
return 0
}
return logRecur(n: n / 2) + 1
}
/* */
func linearLogRecur(n: Int) -> Int {
if n <= 1 {
return 1
}
var count = linearLogRecur(n: n / 2) + linearLogRecur(n: n / 2)
for _ in stride(from: 0, to: n, by: 1) {
count += 1
}
return count
}
/* */
func factorialRecur(n: Int) -> Int {
if n == 0 {
return 1
}
var count = 0
// 1 n
for _ in 0 ..< n {
count += factorialRecur(n: n - 1)
}
return count
}
@main
enum TimeComplexity {
/* Driver Code */
static func main() {
// n
let n = 8
print("入力データサイズ n = \(n)")
var count = constant(n: n)
print("定数時間の操作回数 = \(count)")
count = linear(n: n)
print("線形時間の操作回数 = \(count)")
count = arrayTraversal(nums: Array(repeating: 0, count: n))
print("線形時間(配列の走査)の操作回数 = \(count)")
count = quadratic(n: n)
print("二乗時間の操作回数 = \(count)")
var nums = Array(stride(from: n, to: 0, by: -1)) // [n,n-1,...,2,1]
count = bubbleSort(nums: &nums)
print("二乗時間(バブルソート)の操作回数 = \(count)")
count = exponential(n: n)
print("指数時間(ループ実装)の操作回数 = \(count)")
count = expRecur(n: n)
print("指数時間(再帰実装)の操作回数 = \(count)")
count = logarithmic(n: n)
print("対数時間(ループ実装)の操作回数 = \(count)")
count = logRecur(n: n)
print("対数時間(再帰実装)の操作回数 = \(count)")
count = linearLogRecur(n: n)
print("線形対数時間(再帰実装)の操作回数 = \(count)")
count = factorialRecur(n: n)
print("階乗時間(再帰実装)の操作回数 = \(count)")
}
}
@@ -0,0 +1,40 @@
/**
* File: worst_best_time_complexity.swift
* Created Time: 2022-12-26
* Author: nuomi1 (nuomi1@qq.com)
*/
/* { 1, 2, ..., n } */
func randomNumbers(n: Int) -> [Int] {
// nums = { 1, 2, 3, ..., n }
var nums = Array(1 ... n)
//
nums.shuffle()
return nums
}
/* nums 1 */
func findOne(nums: [Int]) -> Int {
for i in nums.indices {
// 1 O(1)
// 1 O(n)
if nums[i] == 1 {
return i
}
}
return -1
}
@main
enum WorstBestTimeComplexity {
/* Driver Code */
static func main() {
for _ in 0 ..< 10 {
let n = 100
let nums = randomNumbers(n: n)
let index = findOne(nums: nums)
print("配列 [ 1, 2, ..., n ] をシャッフルした後 = \(nums)")
print("数値 1 のインデックスは \(index)")
}
}
}
@@ -0,0 +1,44 @@
/**
* File: binary_search_recur.swift
* Created Time: 2023-09-02
* Author: nuomi1 (nuomi1@qq.com)
*/
/* f(i, j) */
func dfs(nums: [Int], target: Int, i: Int, j: Int) -> Int {
// -1
if i > j {
return -1
}
// m
let m = (i + j) / 2
if nums[m] < target {
// f(m+1, j)
return dfs(nums: nums, target: target, i: m + 1, j: j)
} else if nums[m] > target {
// f(i, m-1)
return dfs(nums: nums, target: target, i: i, j: m - 1)
} else {
//
return m
}
}
/* */
func binarySearch(nums: [Int], target: Int) -> Int {
// f(0, n-1)
dfs(nums: nums, target: target, i: nums.startIndex, j: nums.endIndex - 1)
}
@main
enum BinarySearchRecur {
/* Driver Code */
static func main() {
let target = 6
let nums = [1, 3, 6, 8, 12, 15, 23, 26, 31, 35]
//
let index = binarySearch(nums: nums, target: target)
print("対象要素 6 のインデックス = \(index)")
}
}
@@ -0,0 +1,47 @@
/**
* File: build_tree.swift
* Created Time: 2023-09-02
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
/* */
func dfs(preorder: [Int], inorderMap: [Int: Int], i: Int, l: Int, r: Int) -> TreeNode? {
//
if r - l < 0 {
return nil
}
//
let root = TreeNode(x: preorder[i])
// m
let m = inorderMap[preorder[i]]!
//
root.left = dfs(preorder: preorder, inorderMap: inorderMap, i: i + 1, l: l, r: m - 1)
//
root.right = dfs(preorder: preorder, inorderMap: inorderMap, i: i + 1 + m - l, l: m + 1, r: r)
//
return root
}
/* */
func buildTree(preorder: [Int], inorder: [Int]) -> TreeNode? {
// inorder
let inorderMap = inorder.enumerated().reduce(into: [:]) { $0[$1.element] = $1.offset }
return dfs(preorder: preorder, inorderMap: inorderMap, i: inorder.startIndex, l: inorder.startIndex, r: inorder.endIndex - 1)
}
@main
enum BuildTree {
/* Driver Code */
static func main() {
let preorder = [3, 9, 2, 1, 7]
let inorder = [9, 3, 1, 2, 7]
print("前順走査 = \(preorder)")
print("中順走査 = \(inorder)")
let root = buildTree(preorder: preorder, inorder: inorder)
print("構築した二分木は:")
PrintUtil.printTree(root: root)
}
}
@@ -0,0 +1,58 @@
/**
* File: hanota.swift
* Created Time: 2023-09-02
* Author: nuomi1 (nuomi1@qq.com)
*/
/* 1 */
func move(src: inout [Int], tar: inout [Int]) {
// src 1
let pan = src.popLast()!
// tar
tar.append(pan)
}
/* f(i) */
func dfs(i: Int, src: inout [Int], buf: inout [Int], tar: inout [Int]) {
// src 1 tar
if i == 1 {
move(src: &src, tar: &tar)
return
}
// f(i-1)src i-1 tar buf
dfs(i: i - 1, src: &src, buf: &tar, tar: &buf)
// f(1)src 1 tar
move(src: &src, tar: &tar)
// f(i-1)buf i-1 src tar
dfs(i: i - 1, src: &buf, buf: &src, tar: &tar)
}
/* */
func solveHanota(A: inout [Int], B: inout [Int], C: inout [Int]) {
let n = A.count
//
// src n B C
dfs(i: n, src: &A, buf: &B, tar: &C)
}
@main
enum Hanota {
/* Driver Code */
static func main() {
//
var A = [5, 4, 3, 2, 1]
var B: [Int] = []
var C: [Int] = []
print("初期状態:")
print("A = \(A)")
print("B = \(B)")
print("C = \(C)")
solveHanota(A: &A, B: &B, C: &C)
print("円盤の移動完了後:")
print("A = \(A)")
print("B = \(B)")
print("C = \(C)")
}
}
@@ -0,0 +1,44 @@
/**
* File: climbing_stairs_backtrack.swift
* Created Time: 2023-07-15
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
func backtrack(choices: [Int], state: Int, n: Int, res: inout [Int]) {
// n 1
if state == n {
res[0] += 1
}
//
for choice in choices {
// : n
if state + choice > n {
continue
}
// :
backtrack(choices: choices, state: state + choice, n: n, res: &res)
//
}
}
/* */
func climbingStairsBacktrack(n: Int) -> Int {
let choices = [1, 2] // 1 2
let state = 0 // 0
var res: [Int] = []
res.append(0) // res[0] 使
backtrack(choices: choices, state: state, n: n, res: &res)
return res[0]
}
@main
enum ClimbingStairsBacktrack {
/* Driver Code */
static func main() {
let n = 9
let res = climbingStairsBacktrack(n: n)
print("\(n) 段の階段を上る方法は全部で \(res) 通り")
}
}
@@ -0,0 +1,36 @@
/**
* File: climbing_stairs_constraint_dp.swift
* Created Time: 2023-07-15
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
func climbingStairsConstraintDP(n: Int) -> Int {
if n == 1 || n == 2 {
return 1
}
// dp
var dp = Array(repeating: Array(repeating: 0, count: 3), count: n + 1)
//
dp[1][1] = 1
dp[1][2] = 0
dp[2][1] = 0
dp[2][2] = 1
//
for i in 3 ... n {
dp[i][1] = dp[i - 1][2]
dp[i][2] = dp[i - 2][1] + dp[i - 2][2]
}
return dp[n][1] + dp[n][2]
}
@main
enum ClimbingStairsConstraintDP {
/* Driver Code */
static func main() {
let n = 9
let res = climbingStairsConstraintDP(n: n)
print("\(n) 段の階段を上る方法は全部で \(res) 通り")
}
}
@@ -0,0 +1,32 @@
/**
* File: climbing_stairs_dfs.swift
* Created Time: 2023-07-15
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
func dfs(i: Int) -> Int {
// dp[1] dp[2]
if i == 1 || i == 2 {
return i
}
// dp[i] = dp[i-1] + dp[i-2]
let count = dfs(i: i - 1) + dfs(i: i - 2)
return count
}
/* */
func climbingStairsDFS(n: Int) -> Int {
dfs(i: n)
}
@main
enum ClimbingStairsDFS {
/* Driver Code */
static func main() {
let n = 9
let res = climbingStairsDFS(n: n)
print("\(n) 段の階段を上る方法は全部で \(res) 通り")
}
}
@@ -0,0 +1,40 @@
/**
* File: climbing_stairs_dfs_mem.swift
* Created Time: 2023-07-15
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
func dfs(i: Int, mem: inout [Int]) -> Int {
// dp[1] dp[2]
if i == 1 || i == 2 {
return i
}
// dp[i]
if mem[i] != -1 {
return mem[i]
}
// dp[i] = dp[i-1] + dp[i-2]
let count = dfs(i: i - 1, mem: &mem) + dfs(i: i - 2, mem: &mem)
// dp[i]
mem[i] = count
return count
}
/* */
func climbingStairsDFSMem(n: Int) -> Int {
// mem[i] i -1
var mem = Array(repeating: -1, count: n + 1)
return dfs(i: n, mem: &mem)
}
@main
enum ClimbingStairsDFSMem {
/* Driver Code */
static func main() {
let n = 9
let res = climbingStairsDFSMem(n: n)
print("\(n) 段の階段を上る方法は全部で \(res) 通り")
}
}
@@ -0,0 +1,49 @@
/**
* File: climbing_stairs_dp.swift
* Created Time: 2023-07-15
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
func climbingStairsDP(n: Int) -> Int {
if n == 1 || n == 2 {
return n
}
// dp
var dp = Array(repeating: 0, count: n + 1)
//
dp[1] = 1
dp[2] = 2
//
for i in 3 ... n {
dp[i] = dp[i - 1] + dp[i - 2]
}
return dp[n]
}
/* */
func climbingStairsDPComp(n: Int) -> Int {
if n == 1 || n == 2 {
return n
}
var a = 1
var b = 2
for _ in 3 ... n {
(a, b) = (b, a + b)
}
return b
}
@main
enum ClimbingStairsDP {
/* Driver Code */
static func main() {
let n = 9
var res = climbingStairsDP(n: n)
print("\(n) 段の階段を上る方法は全部で \(res) 通り")
res = climbingStairsDPComp(n: n)
print("\(n) 段の階段を上る方法は全部で \(res) 通り")
}
}
@@ -0,0 +1,69 @@
/**
* File: coin_change.swift
* Created Time: 2023-07-15
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
func coinChangeDP(coins: [Int], amt: Int) -> Int {
let n = coins.count
let MAX = amt + 1
// dp
var dp = Array(repeating: Array(repeating: 0, count: amt + 1), count: n + 1)
//
for a in 1 ... amt {
dp[0][a] = MAX
}
// :
for i in 1 ... n {
for a in 1 ... amt {
if coins[i - 1] > a {
// i
dp[i][a] = dp[i - 1][a]
} else {
// i
dp[i][a] = min(dp[i - 1][a], dp[i][a - coins[i - 1]] + 1)
}
}
}
return dp[n][amt] != MAX ? dp[n][amt] : -1
}
/* */
func coinChangeDPComp(coins: [Int], amt: Int) -> Int {
let n = coins.count
let MAX = amt + 1
// dp
var dp = Array(repeating: MAX, count: amt + 1)
dp[0] = 0
//
for i in 1 ... n {
for a in 1 ... amt {
if coins[i - 1] > a {
// i
dp[a] = dp[a]
} else {
// i
dp[a] = min(dp[a], dp[a - coins[i - 1]] + 1)
}
}
}
return dp[amt] != MAX ? dp[amt] : -1
}
@main
enum CoinChange {
/* Driver Code */
static func main() {
let coins = [1, 2, 5]
let amt = 4
//
var res = coinChangeDP(coins: coins, amt: amt)
print("目標金額に必要な最小硬貨枚数は \(res)")
//
res = coinChangeDPComp(coins: coins, amt: amt)
print("目標金額に必要な最小硬貨枚数は \(res)")
}
}
@@ -0,0 +1,67 @@
/**
* File: coin_change_ii.swift
* Created Time: 2023-07-16
* Author: nuomi1 (nuomi1@qq.com)
*/
/* II */
func coinChangeIIDP(coins: [Int], amt: Int) -> Int {
let n = coins.count
// dp
var dp = Array(repeating: Array(repeating: 0, count: amt + 1), count: n + 1)
//
for i in 0 ... n {
dp[i][0] = 1
}
//
for i in 1 ... n {
for a in 1 ... amt {
if coins[i - 1] > a {
// i
dp[i][a] = dp[i - 1][a]
} else {
// i
dp[i][a] = dp[i - 1][a] + dp[i][a - coins[i - 1]]
}
}
}
return dp[n][amt]
}
/* II */
func coinChangeIIDPComp(coins: [Int], amt: Int) -> Int {
let n = coins.count
// dp
var dp = Array(repeating: 0, count: amt + 1)
dp[0] = 1
//
for i in 1 ... n {
for a in 1 ... amt {
if coins[i - 1] > a {
// i
dp[a] = dp[a]
} else {
// i
dp[a] = dp[a] + dp[a - coins[i - 1]]
}
}
}
return dp[amt]
}
@main
enum CoinChangeII {
/* Driver Code */
static func main() {
let coins = [1, 2, 5]
let amt = 5
//
var res = coinChangeIIDP(coins: coins, amt: amt)
print("目標金額を作る硬貨の組み合わせ数は \(res)")
//
res = coinChangeIIDPComp(coins: coins, amt: amt)
print("目標金額を作る硬貨の組み合わせ数は \(res)")
}
}
@@ -0,0 +1,147 @@
/**
* File: edit_distance.swift
* Created Time: 2023-07-16
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
func editDistanceDFS(s: String, t: String, i: Int, j: Int) -> Int {
// s t 0
if i == 0, j == 0 {
return 0
}
// s t
if i == 0 {
return j
}
// t s
if j == 0 {
return i
}
// 2 2
if s.utf8CString[i - 1] == t.utf8CString[j - 1] {
return editDistanceDFS(s: s, t: t, i: i - 1, j: j - 1)
}
// = 3 + 1
let insert = editDistanceDFS(s: s, t: t, i: i, j: j - 1)
let delete = editDistanceDFS(s: s, t: t, i: i - 1, j: j)
let replace = editDistanceDFS(s: s, t: t, i: i - 1, j: j - 1)
//
return min(min(insert, delete), replace) + 1
}
/* */
func editDistanceDFSMem(s: String, t: String, mem: inout [[Int]], i: Int, j: Int) -> Int {
// s t 0
if i == 0, j == 0 {
return 0
}
// s t
if i == 0 {
return j
}
// t s
if j == 0 {
return i
}
//
if mem[i][j] != -1 {
return mem[i][j]
}
// 2 2
if s.utf8CString[i - 1] == t.utf8CString[j - 1] {
return editDistanceDFS(s: s, t: t, i: i - 1, j: j - 1)
}
// = 3 + 1
let insert = editDistanceDFS(s: s, t: t, i: i, j: j - 1)
let delete = editDistanceDFS(s: s, t: t, i: i - 1, j: j)
let replace = editDistanceDFS(s: s, t: t, i: i - 1, j: j - 1)
//
mem[i][j] = min(min(insert, delete), replace) + 1
return mem[i][j]
}
/* */
func editDistanceDP(s: String, t: String) -> Int {
let n = s.utf8CString.count
let m = t.utf8CString.count
var dp = Array(repeating: Array(repeating: 0, count: m + 1), count: n + 1)
//
for i in 1 ... n {
dp[i][0] = i
}
for j in 1 ... m {
dp[0][j] = j
}
// :
for i in 1 ... n {
for j in 1 ... m {
if s.utf8CString[i - 1] == t.utf8CString[j - 1] {
// 2 2
dp[i][j] = dp[i - 1][j - 1]
} else {
// = 3 + 1
dp[i][j] = min(min(dp[i][j - 1], dp[i - 1][j]), dp[i - 1][j - 1]) + 1
}
}
}
return dp[n][m]
}
/* */
func editDistanceDPComp(s: String, t: String) -> Int {
let n = s.utf8CString.count
let m = t.utf8CString.count
var dp = Array(repeating: 0, count: m + 1)
//
for j in 1 ... m {
dp[j] = j
}
//
for i in 1 ... n {
//
var leftup = dp[0] // dp[i-1, j-1]
dp[0] = i
//
for j in 1 ... m {
let temp = dp[j]
if s.utf8CString[i - 1] == t.utf8CString[j - 1] {
// 2 2
dp[j] = leftup
} else {
// = 3 + 1
dp[j] = min(min(dp[j - 1], dp[j]), leftup) + 1
}
leftup = temp // dp[i-1, j-1]
}
}
return dp[m]
}
@main
enum EditDistance {
/* Driver Code */
static func main() {
let s = "bag"
let t = "pack"
let n = s.utf8CString.count
let m = t.utf8CString.count
//
var res = editDistanceDFS(s: s, t: t, i: n, j: m)
print("\(s)\(t) に変更するには最小で \(res) 回の編集が必要")
//
var mem = Array(repeating: Array(repeating: -1, count: m + 1), count: n + 1)
res = editDistanceDFSMem(s: s, t: t, mem: &mem, i: n, j: m)
print("\(s)\(t) に変更するには最小で \(res) 回の編集が必要")
//
res = editDistanceDP(s: s, t: t)
print("\(s)\(t) に変更するには最小で \(res) 回の編集が必要")
//
res = editDistanceDPComp(s: s, t: t)
print("\(s)\(t) に変更するには最小で \(res) 回の編集が必要")
}
}
@@ -0,0 +1,110 @@
/**
* File: knapsack.swift
* Created Time: 2023-07-15
* Author: nuomi1 (nuomi1@qq.com)
*/
/* 0-1 */
func knapsackDFS(wgt: [Int], val: [Int], i: Int, c: Int) -> Int {
// 0
if i == 0 || c == 0 {
return 0
}
//
if wgt[i - 1] > c {
return knapsackDFS(wgt: wgt, val: val, i: i - 1, c: c)
}
// i
let no = knapsackDFS(wgt: wgt, val: val, i: i - 1, c: c)
let yes = knapsackDFS(wgt: wgt, val: val, i: i - 1, c: c - wgt[i - 1]) + val[i - 1]
// 2
return max(no, yes)
}
/* 0-1 */
func knapsackDFSMem(wgt: [Int], val: [Int], mem: inout [[Int]], i: Int, c: Int) -> Int {
// 0
if i == 0 || c == 0 {
return 0
}
//
if mem[i][c] != -1 {
return mem[i][c]
}
//
if wgt[i - 1] > c {
return knapsackDFSMem(wgt: wgt, val: val, mem: &mem, i: i - 1, c: c)
}
// i
let no = knapsackDFSMem(wgt: wgt, val: val, mem: &mem, i: i - 1, c: c)
let yes = knapsackDFSMem(wgt: wgt, val: val, mem: &mem, i: i - 1, c: c - wgt[i - 1]) + val[i - 1]
// 2
mem[i][c] = max(no, yes)
return mem[i][c]
}
/* 0-1 */
func knapsackDP(wgt: [Int], val: [Int], cap: Int) -> Int {
let n = wgt.count
// dp
var dp = Array(repeating: Array(repeating: 0, count: cap + 1), count: n + 1)
//
for i in 1 ... n {
for c in 1 ... cap {
if wgt[i - 1] > c {
// i
dp[i][c] = dp[i - 1][c]
} else {
// i
dp[i][c] = max(dp[i - 1][c], dp[i - 1][c - wgt[i - 1]] + val[i - 1])
}
}
}
return dp[n][cap]
}
/* 0-1 */
func knapsackDPComp(wgt: [Int], val: [Int], cap: Int) -> Int {
let n = wgt.count
// dp
var dp = Array(repeating: 0, count: cap + 1)
//
for i in 1 ... n {
//
for c in (1 ... cap).reversed() {
if wgt[i - 1] <= c {
// i
dp[c] = max(dp[c], dp[c - wgt[i - 1]] + val[i - 1])
}
}
}
return dp[cap]
}
@main
enum Knapsack {
/* Driver Code */
static func main() {
let wgt = [10, 20, 30, 40, 50]
let val = [50, 120, 150, 210, 240]
let cap = 50
let n = wgt.count
//
var res = knapsackDFS(wgt: wgt, val: val, i: n, c: cap)
print("ナップサック容量を超えない最大価値は \(res)")
//
var mem = Array(repeating: Array(repeating: -1, count: cap + 1), count: n + 1)
res = knapsackDFSMem(wgt: wgt, val: val, mem: &mem, i: n, c: cap)
print("ナップサック容量を超えない最大価値は \(res)")
//
res = knapsackDP(wgt: wgt, val: val, cap: cap)
print("ナップサック容量を超えない最大価値は \(res)")
//
res = knapsackDPComp(wgt: wgt, val: val, cap: cap)
print("ナップサック容量を超えない最大価値は \(res)")
}
}
@@ -0,0 +1,51 @@
/**
* File: min_cost_climbing_stairs_dp.swift
* Created Time: 2023-07-15
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
func minCostClimbingStairsDP(cost: [Int]) -> Int {
let n = cost.count - 1
if n == 1 || n == 2 {
return cost[n]
}
// dp
var dp = Array(repeating: 0, count: n + 1)
//
dp[1] = cost[1]
dp[2] = cost[2]
//
for i in 3 ... n {
dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i]
}
return dp[n]
}
/* */
func minCostClimbingStairsDPComp(cost: [Int]) -> Int {
let n = cost.count - 1
if n == 1 || n == 2 {
return cost[n]
}
var (a, b) = (cost[1], cost[2])
for i in 3 ... n {
(a, b) = (b, min(a, b) + cost[i])
}
return b
}
@main
enum MinCostClimbingStairsDP {
/* Driver Code */
static func main() {
let cost = [0, 1, 10, 1, 1, 1, 10, 1, 1, 10, 1]
print("入力された階段のコスト一覧は \(cost)")
var res = minCostClimbingStairsDP(cost: cost)
print("階段を上り切る最小コストは \(res)")
res = minCostClimbingStairsDPComp(cost: cost)
print("階段を上り切る最小コストは \(res)")
}
}
@@ -0,0 +1,123 @@
/**
* File: min_path_sum.swift
* Created Time: 2023-07-15
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
func minPathSumDFS(grid: [[Int]], i: Int, j: Int) -> Int {
//
if i == 0, j == 0 {
return grid[0][0]
}
// +
if i < 0 || j < 0 {
return .max
}
// (i-1, j) (i, j-1)
let up = minPathSumDFS(grid: grid, i: i - 1, j: j)
let left = minPathSumDFS(grid: grid, i: i, j: j - 1)
// (i, j)
return min(left, up) + grid[i][j]
}
/* */
func minPathSumDFSMem(grid: [[Int]], mem: inout [[Int]], i: Int, j: Int) -> Int {
//
if i == 0, j == 0 {
return grid[0][0]
}
// +
if i < 0 || j < 0 {
return .max
}
//
if mem[i][j] != -1 {
return mem[i][j]
}
//
let up = minPathSumDFSMem(grid: grid, mem: &mem, i: i - 1, j: j)
let left = minPathSumDFSMem(grid: grid, mem: &mem, i: i, j: j - 1)
// (i, j)
mem[i][j] = min(left, up) + grid[i][j]
return mem[i][j]
}
/* */
func minPathSumDP(grid: [[Int]]) -> Int {
let n = grid.count
let m = grid[0].count
// dp
var dp = Array(repeating: Array(repeating: 0, count: m), count: n)
dp[0][0] = grid[0][0]
//
for j in 1 ..< m {
dp[0][j] = dp[0][j - 1] + grid[0][j]
}
//
for i in 1 ..< n {
dp[i][0] = dp[i - 1][0] + grid[i][0]
}
// :
for i in 1 ..< n {
for j in 1 ..< m {
dp[i][j] = min(dp[i][j - 1], dp[i - 1][j]) + grid[i][j]
}
}
return dp[n - 1][m - 1]
}
/* */
func minPathSumDPComp(grid: [[Int]]) -> Int {
let n = grid.count
let m = grid[0].count
// dp
var dp = Array(repeating: 0, count: m)
//
dp[0] = grid[0][0]
for j in 1 ..< m {
dp[j] = dp[j - 1] + grid[0][j]
}
//
for i in 1 ..< n {
//
dp[0] = dp[0] + grid[i][0]
//
for j in 1 ..< m {
dp[j] = min(dp[j - 1], dp[j]) + grid[i][j]
}
}
return dp[m - 1]
}
@main
enum MinPathSum {
/* Driver Code */
static func main() {
let grid = [
[1, 3, 1, 5],
[2, 2, 4, 2],
[5, 3, 2, 1],
[4, 3, 5, 2],
]
let n = grid.count
let m = grid[0].count
//
var res = minPathSumDFS(grid: grid, i: n - 1, j: m - 1)
print("左上から右下までの最小経路和は \(res)")
//
var mem = Array(repeating: Array(repeating: -1, count: m), count: n)
res = minPathSumDFSMem(grid: grid, mem: &mem, i: n - 1, j: m - 1)
print("左上から右下までの最小経路和は \(res)")
//
res = minPathSumDP(grid: grid)
print("左上から右下までの最小経路和は \(res)")
//
res = minPathSumDPComp(grid: grid)
print("左上から右下までの最小経路和は \(res)")
}
}
@@ -0,0 +1,63 @@
/**
* File: unbounded_knapsack.swift
* Created Time: 2023-07-15
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
func unboundedKnapsackDP(wgt: [Int], val: [Int], cap: Int) -> Int {
let n = wgt.count
// dp
var dp = Array(repeating: Array(repeating: 0, count: cap + 1), count: n + 1)
//
for i in 1 ... n {
for c in 1 ... cap {
if wgt[i - 1] > c {
// i
dp[i][c] = dp[i - 1][c]
} else {
// i
dp[i][c] = max(dp[i - 1][c], dp[i][c - wgt[i - 1]] + val[i - 1])
}
}
}
return dp[n][cap]
}
/* */
func unboundedKnapsackDPComp(wgt: [Int], val: [Int], cap: Int) -> Int {
let n = wgt.count
// dp
var dp = Array(repeating: 0, count: cap + 1)
//
for i in 1 ... n {
for c in 1 ... cap {
if wgt[i - 1] > c {
// i
dp[c] = dp[c]
} else {
// i
dp[c] = max(dp[c], dp[c - wgt[i - 1]] + val[i - 1])
}
}
}
return dp[cap]
}
@main
enum UnboundedKnapsack {
/* Driver Code */
static func main() {
let wgt = [1, 2, 3]
let val = [5, 11, 15]
let cap = 4
//
var res = unboundedKnapsackDP(wgt: wgt, val: val, cap: cap)
print("ナップサック容量を超えない最大価値は \(res)")
//
res = unboundedKnapsackDPComp(wgt: wgt, val: val, cap: cap)
print("ナップサック容量を超えない最大価値は \(res)")
}
}
@@ -0,0 +1,121 @@
/**
* File: graph_adjacency_list.swift
* Created Time: 2023-02-01
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
/* */
public class GraphAdjList {
// key value
public private(set) var adjList: [Vertex: [Vertex]]
/* */
public init(edges: [[Vertex]]) {
adjList = [:]
//
for edge in edges {
addVertex(vet: edge[0])
addVertex(vet: edge[1])
addEdge(vet1: edge[0], vet2: edge[1])
}
}
/* */
public func size() -> Int {
adjList.count
}
/* */
public func addEdge(vet1: Vertex, vet2: Vertex) {
if adjList[vet1] == nil || adjList[vet2] == nil || vet1 == vet2 {
fatalError("引数エラー")
}
// vet1 - vet2
adjList[vet1]?.append(vet2)
adjList[vet2]?.append(vet1)
}
/* */
public func removeEdge(vet1: Vertex, vet2: Vertex) {
if adjList[vet1] == nil || adjList[vet2] == nil || vet1 == vet2 {
fatalError("引数エラー")
}
// vet1 - vet2
adjList[vet1]?.removeAll { $0 == vet2 }
adjList[vet2]?.removeAll { $0 == vet1 }
}
/* */
public func addVertex(vet: Vertex) {
if adjList[vet] != nil {
return
}
//
adjList[vet] = []
}
/* */
public func removeVertex(vet: Vertex) {
if adjList[vet] == nil {
fatalError("引数エラー")
}
// vet
adjList.removeValue(forKey: vet)
// vet
for key in adjList.keys {
adjList[key]?.removeAll { $0 == vet }
}
}
/* */
public func print() {
Swift.print("隣接リスト =")
for (vertex, list) in adjList {
let list = list.map { $0.val }
Swift.print("\(vertex.val): \(list),")
}
}
}
#if !TARGET
@main
enum GraphAdjacencyList {
/* Driver Code */
static func main() {
/* */
let v = Vertex.valsToVets(vals: [1, 3, 2, 5, 4])
let edges = [[v[0], v[1]], [v[0], v[3]], [v[1], v[2]], [v[2], v[3]], [v[2], v[4]], [v[3], v[4]]]
let graph = GraphAdjList(edges: edges)
print("\n初期化後のグラフ")
graph.print()
/* */
// 1, 2 v[0], v[2]
graph.addEdge(vet1: v[0], vet2: v[2])
print("\n辺 1-2 を追加後のグラフ")
graph.print()
/* */
// 1, 3 v[0], v[1]
graph.removeEdge(vet1: v[0], vet2: v[1])
print("\n辺 1-3 を削除後のグラフ")
graph.print()
/* */
let v5 = Vertex(val: 6)
graph.addVertex(vet: v5)
print("\n頂点 6 を追加後のグラフ")
graph.print()
/* */
// 3 v[1]
graph.removeVertex(vet: v[1])
print("\n頂点 3 を削除後のグラフ")
graph.print()
}
}
#endif
@@ -0,0 +1,121 @@
/**
* File: graph_adjacency_list.swift
* Created Time: 2023-02-01
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
/* */
public class GraphAdjList {
// key value
public private(set) var adjList: [Vertex: [Vertex]]
/* */
public init(edges: [[Vertex]]) {
adjList = [:]
//
for edge in edges {
addVertex(vet: edge[0])
addVertex(vet: edge[1])
addEdge(vet1: edge[0], vet2: edge[1])
}
}
/* */
public func size() -> Int {
adjList.count
}
/* */
public func addEdge(vet1: Vertex, vet2: Vertex) {
if adjList[vet1] == nil || adjList[vet2] == nil || vet1 == vet2 {
fatalError("引数エラー")
}
// vet1 - vet2
adjList[vet1]?.append(vet2)
adjList[vet2]?.append(vet1)
}
/* */
public func removeEdge(vet1: Vertex, vet2: Vertex) {
if adjList[vet1] == nil || adjList[vet2] == nil || vet1 == vet2 {
fatalError("引数エラー")
}
// vet1 - vet2
adjList[vet1]?.removeAll { $0 == vet2 }
adjList[vet2]?.removeAll { $0 == vet1 }
}
/* */
public func addVertex(vet: Vertex) {
if adjList[vet] != nil {
return
}
//
adjList[vet] = []
}
/* */
public func removeVertex(vet: Vertex) {
if adjList[vet] == nil {
fatalError("引数エラー")
}
// vet
adjList.removeValue(forKey: vet)
// vet
for key in adjList.keys {
adjList[key]?.removeAll { $0 == vet }
}
}
/* */
public func print() {
Swift.print("隣接リスト =")
for (vertex, list) in adjList {
let list = list.map { $0.val }
Swift.print("\(vertex.val): \(list),")
}
}
}
#if !TARGET
@main
enum GraphAdjacencyList {
/* Driver Code */
static func main() {
/* */
let v = Vertex.valsToVets(vals: [1, 3, 2, 5, 4])
let edges = [[v[0], v[1]], [v[0], v[3]], [v[1], v[2]], [v[2], v[3]], [v[2], v[4]], [v[3], v[4]]]
let graph = GraphAdjList(edges: edges)
print("\n初期化後のグラフ")
graph.print()
/* */
// 1, 2 v[0], v[2]
graph.addEdge(vet1: v[0], vet2: v[2])
print("\n辺 1-2 を追加後のグラフ")
graph.print()
/* */
// 1, 3 v[0], v[1]
graph.removeEdge(vet1: v[0], vet2: v[1])
print("\n辺 1-3 を削除後のグラフ")
graph.print()
/* */
let v5 = Vertex(val: 6)
graph.addVertex(vet: v5)
print("\n頂点 6 を追加後のグラフ")
graph.print()
/* */
// 3 v[1]
graph.removeVertex(vet: v[1])
print("\n頂点 3 を削除後のグラフ")
graph.print()
}
}
#endif
@@ -0,0 +1,130 @@
/**
* File: graph_adjacency_matrix.swift
* Created Time: 2023-02-01
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
/* */
class GraphAdjMat {
private var vertices: [Int] //
private var adjMat: [[Int]] //
/* */
init(vertices: [Int], edges: [[Int]]) {
self.vertices = []
adjMat = []
//
for val in vertices {
addVertex(val: val)
}
//
// edges vertices
for e in edges {
addEdge(i: e[0], j: e[1])
}
}
/* */
func size() -> Int {
vertices.count
}
/* */
func addVertex(val: Int) {
let n = size()
//
vertices.append(val)
// 1
let newRow = Array(repeating: 0, count: n)
adjMat.append(newRow)
// 1
for i in adjMat.indices {
adjMat[i].append(0)
}
}
/* */
func removeVertex(index: Int) {
if index >= size() {
fatalError("範囲外")
}
// index
vertices.remove(at: index)
// index
adjMat.remove(at: index)
// index
for i in adjMat.indices {
adjMat[i].remove(at: index)
}
}
/* */
// i, j vertices
func addEdge(i: Int, j: Int) {
//
if i < 0 || j < 0 || i >= size() || j >= size() || i == j {
fatalError("範囲外")
}
// (i, j) == (j, i)
adjMat[i][j] = 1
adjMat[j][i] = 1
}
/* */
// i, j vertices
func removeEdge(i: Int, j: Int) {
//
if i < 0 || j < 0 || i >= size() || j >= size() || i == j {
fatalError("範囲外")
}
adjMat[i][j] = 0
adjMat[j][i] = 0
}
/* */
func print() {
Swift.print("頂点リスト = ", terminator: "")
Swift.print(vertices)
Swift.print("隣接行列 =")
PrintUtil.printMatrix(matrix: adjMat)
}
}
@main
enum GraphAdjacencyMatrix {
/* Driver Code */
static func main() {
/* */
// edges vertices
let vertices = [1, 3, 2, 5, 4]
let edges = [[0, 1], [1, 2], [2, 3], [0, 3], [2, 4], [3, 4]]
let graph = GraphAdjMat(vertices: vertices, edges: edges)
print("\n初期化後のグラフ")
graph.print()
/* */
// 1, 2 0, 2
graph.addEdge(i: 0, j: 2)
print("\n辺 1-2 を追加後のグラフ")
graph.print()
/* */
// 1, 3 0, 1
graph.removeEdge(i: 0, j: 1)
print("\n辺 1-3 を削除後のグラフ")
graph.print()
/* */
graph.addVertex(val: 6)
print("\n頂点 6 を追加後のグラフ")
graph.print()
/* */
// 3 1
graph.removeVertex(index: 1)
print("\n頂点 3 を削除後のグラフ")
graph.print()
}
}
@@ -0,0 +1,56 @@
/**
* File: graph_bfs.swift
* Created Time: 2023-02-21
* Author: nuomi1 (nuomi1@qq.com)
*/
import graph_adjacency_list_target
import utils
/* */
//
func graphBFS(graph: GraphAdjList, startVet: Vertex) -> [Vertex] {
//
var res: [Vertex] = []
//
var visited: Set<Vertex> = [startVet]
// BFS
var que: [Vertex] = [startVet]
// vet
while !que.isEmpty {
let vet = que.removeFirst() //
res.append(vet) //
//
for adjVet in graph.adjList[vet] ?? [] {
if visited.contains(adjVet) {
continue //
}
que.append(adjVet) //
visited.insert(adjVet) //
}
}
//
return res
}
@main
enum GraphBFS {
/* Driver Code */
static func main() {
/* */
let v = Vertex.valsToVets(vals: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
let edges = [
[v[0], v[1]], [v[0], v[3]], [v[1], v[2]], [v[1], v[4]],
[v[2], v[5]], [v[3], v[4]], [v[3], v[6]], [v[4], v[5]],
[v[4], v[7]], [v[5], v[8]], [v[6], v[7]], [v[7], v[8]],
]
let graph = GraphAdjList(edges: edges)
print("\n初期化後のグラフ")
graph.print()
/* */
let res = graphBFS(graph: graph, startVet: v[0])
print("\n幅優先探索(BFS)の頂点列")
print(Vertex.vetsToVals(vets: res))
}
}
@@ -0,0 +1,54 @@
/**
* File: graph_dfs.swift
* Created Time: 2023-02-21
* Author: nuomi1 (nuomi1@qq.com)
*/
import graph_adjacency_list_target
import utils
/* */
func dfs(graph: GraphAdjList, visited: inout Set<Vertex>, res: inout [Vertex], vet: Vertex) {
res.append(vet) //
visited.insert(vet) //
//
for adjVet in graph.adjList[vet] ?? [] {
if visited.contains(adjVet) {
continue //
}
//
dfs(graph: graph, visited: &visited, res: &res, vet: adjVet)
}
}
/* */
//
func graphDFS(graph: GraphAdjList, startVet: Vertex) -> [Vertex] {
//
var res: [Vertex] = []
//
var visited: Set<Vertex> = []
dfs(graph: graph, visited: &visited, res: &res, vet: startVet)
return res
}
@main
enum GraphDFS {
/* Driver Code */
static func main() {
/* */
let v = Vertex.valsToVets(vals: [0, 1, 2, 3, 4, 5, 6])
let edges = [
[v[0], v[1]], [v[0], v[3]], [v[1], v[2]],
[v[2], v[5]], [v[4], v[5]], [v[5], v[6]],
]
let graph = GraphAdjList(edges: edges)
print("\n初期化後のグラフ")
graph.print()
/* */
let res = graphDFS(graph: graph, startVet: v[0])
print("\n深さ優先探索(DFS)の頂点列")
print(Vertex.vetsToVals(vets: res))
}
}
@@ -0,0 +1,54 @@
/**
* File: coin_change_greedy.swift
* Created Time: 2023-09-03
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
func coinChangeGreedy(coins: [Int], amt: Int) -> Int {
// coins
var i = coins.count - 1
var count = 0
var amt = amt
//
while amt > 0 {
//
while i > 0 && coins[i] > amt {
i -= 1
}
// coins[i]
amt -= coins[i]
count += 1
}
// -1
return amt == 0 ? count : -1
}
@main
enum CoinChangeGreedy {
/* Driver Code */
static func main() {
//
var coins = [1, 5, 10, 20, 50, 100]
var amt = 186
var res = coinChangeGreedy(coins: coins, amt: amt)
print("\ncoins = \(coins), amount = \(amt)")
print("\(amt) を作るのに必要な最小硬貨枚数は \(res)")
//
coins = [1, 20, 50]
amt = 60
res = coinChangeGreedy(coins: coins, amt: amt)
print("\ncoins = \(coins), amount = \(amt)")
print("\(amt) を作るのに必要な最小硬貨枚数は \(res)")
print("実際に必要な最小枚数は 3、つまり 20 + 20 + 20")
//
coins = [1, 49, 50]
amt = 98
res = coinChangeGreedy(coins: coins, amt: amt)
print("\ncoins = \(coins), amount = \(amt)")
print("\(amt) を作るのに必要な最小硬貨枚数は \(res)")
print("実際に必要な最小枚数は 2、つまり 49 + 49")
}
}
@@ -0,0 +1,57 @@
/**
* File: fractional_knapsack.swift
* Created Time: 2023-09-03
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
class Item {
var w: Int //
var v: Int //
init(w: Int, v: Int) {
self.w = w
self.v = v
}
}
/* */
func fractionalKnapsack(wgt: [Int], val: [Int], cap: Int) -> Double {
// 2
var items = zip(wgt, val).map { Item(w: $0, v: $1) }
// item.v / item.w
items.sort { -(Double($0.v) / Double($0.w)) < -(Double($1.v) / Double($1.w)) }
//
var res = 0.0
var cap = cap
for item in items {
if item.w <= cap {
//
res += Double(item.v)
cap -= item.w
} else {
//
res += Double(item.v) / Double(item.w) * Double(cap)
//
break
}
}
return res
}
@main
enum FractionalKnapsack {
/* Driver Code */
static func main() {
//
let wgt = [10, 20, 30, 40, 50]
//
let val = [50, 120, 150, 210, 240]
//
let cap = 50
//
let res = fractionalKnapsack(wgt: wgt, val: val, cap: cap)
print("ナップサック容量を超えない最大価値は \(res)")
}
}
@@ -0,0 +1,38 @@
/**
* File: max_capacity.swift
* Created Time: 2023-09-03
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
func maxCapacity(ht: [Int]) -> Int {
// i, j
var i = ht.startIndex, j = ht.endIndex - 1
// 0
var res = 0
// 2
while i < j {
//
let cap = min(ht[i], ht[j]) * (j - i)
res = max(res, cap)
//
if ht[i] < ht[j] {
i += 1
} else {
j -= 1
}
}
return res
}
@main
enum MaxCapacity {
/* Driver Code */
static func main() {
let ht = [3, 8, 5, 2, 7, 7, 3, 4]
//
let res = maxCapacity(ht: ht)
print("最大容量は \(res)")
}
}
@@ -0,0 +1,43 @@
/**
* File: max_product_cutting.swift
* Created Time: 2023-09-03
* Author: nuomi1 (nuomi1@qq.com)
*/
import Foundation
func pow(_ x: Int, _ y: Int) -> Int {
Int(Double(truncating: pow(Decimal(x), y) as NSDecimalNumber))
}
/* */
func maxProductCutting(n: Int) -> Int {
// n <= 3 1
if n <= 3 {
return 1 * (n - 1)
}
// 3 a 3 b
let a = n / 3
let b = n % 3
if b == 1 {
// 1 1 * 3 2 * 2
return pow(3, a - 1) * 2 * 2
}
if b == 2 {
// 2
return pow(3, a) * 2
}
// 0
return pow(3, a)
}
@main
enum MaxProductCutting {
static func main() {
let n = 58
//
let res = maxProductCutting(n: n)
print("最大分割積は \(res)")
}
}
@@ -0,0 +1,110 @@
/**
* File: array_hash_map.swift
* Created Time: 2023-01-16
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
/* */
class ArrayHashMap {
private var buckets: [Pair?]
init() {
// 100
buckets = Array(repeating: nil, count: 100)
}
/* */
private func hashFunc(key: Int) -> Int {
let index = key % 100
return index
}
/* */
func get(key: Int) -> String? {
let index = hashFunc(key: key)
let pair = buckets[index]
return pair?.val
}
/* */
func put(key: Int, val: String) {
let pair = Pair(key: key, val: val)
let index = hashFunc(key: key)
buckets[index] = pair
}
/* */
func remove(key: Int) {
let index = hashFunc(key: key)
// nil
buckets[index] = nil
}
/* */
func pairSet() -> [Pair] {
buckets.compactMap { $0 }
}
/* */
func keySet() -> [Int] {
buckets.compactMap { $0?.key }
}
/* */
func valueSet() -> [String] {
buckets.compactMap { $0?.val }
}
/* */
func print() {
for pair in pairSet() {
Swift.print("\(pair.key) -> \(pair.val)")
}
}
}
@main
enum _ArrayHashMap {
/* Driver Code */
static func main() {
/* */
let map = ArrayHashMap()
/* */
// (key, value)
map.put(key: 12836, val: "シャオハー")
map.put(key: 15937, val: "シャオルオ")
map.put(key: 16750, val: "シャオスワン")
map.put(key: 13276, val: "シャオファー")
map.put(key: 10583, val: "シャオヤー")
print("\n追加完了後のハッシュテーブルは\nKey -> Value")
map.print()
/* */
// key value
let name = map.get(key: 15937)!
print("\n学籍番号 15937 を入力すると、名前 \(name) が見つかりました")
/* */
// (key, value)
map.remove(key: 10583)
print("\n10583 を削除後のハッシュテーブルは\nKey -> Value")
map.print()
/* */
print("\nキーと値の組 Key->Value を走査")
for pair in map.pairSet() {
print("\(pair.key) -> \(pair.val)")
}
print("\nキー Key を個別に走査")
for key in map.keySet() {
print(key)
}
print("\n値 Value を個別に走査")
for val in map.valueSet() {
print(val)
}
}
}
@@ -0,0 +1,37 @@
/**
* File: built_in_hash.swift
* Created Time: 2023-07-01
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
@main
enum BuiltInHash {
/* Driver Code */
static func main() {
let num = 3
let hashNum = num.hashValue
print("整数 \(num) のハッシュ値は \(hashNum)")
let bol = true
let hashBol = bol.hashValue
print("真偽値 \(bol) のハッシュ値は \(hashBol)")
let dec = 3.14159
let hashDec = dec.hashValue
print("小数 \(dec) のハッシュ値は \(hashDec)")
let str = "Hello アルゴリズム"
let hashStr = str.hashValue
print("文字列 \(str) のハッシュ値は \(hashStr)")
let arr = [AnyHashable(12836), AnyHashable("シャオハー")]
let hashTup = arr.hashValue
print("配列 \(arr) のハッシュ値は \(hashTup)")
let obj = ListNode(x: 0)
let hashObj = obj.hashValue
print("ノードオブジェクト \(obj) のハッシュ値は \(hashObj)")
}
}
@@ -0,0 +1,51 @@
/**
* File: hash_map.swift
* Created Time: 2023-01-16
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
@main
enum HashMap {
/* Driver Code */
static func main() {
/* */
var map: [Int: String] = [:]
/* */
// (key, value)
map[12836] = "シャオハー"
map[15937] = "シャオルオ"
map[16750] = "シャオスワン"
map[13276] = "シャオファー"
map[10583] = "シャオヤー"
print("\n追加完了後のハッシュテーブルは\nKey -> Value")
PrintUtil.printHashMap(map: map)
/* */
// key value
let name = map[15937]!
print("\n学籍番号 15937 を入力すると、名前 \(name) が見つかりました")
/* */
// (key, value)
map.removeValue(forKey: 10583)
print("\n10583 を削除後のハッシュテーブルは\nKey -> Value")
PrintUtil.printHashMap(map: map)
/* */
print("\nキーと値の組 Key->Value を走査")
for (key, value) in map {
print("\(key) -> \(value)")
}
print("\nキー Key を個別に走査")
for key in map.keys {
print(key)
}
print("\n値 Value を個別に走査")
for value in map.values {
print(value)
}
}
}
@@ -0,0 +1,138 @@
/**
* File: hash_map_chaining.swift
* Created Time: 2023-06-28
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
/* */
class HashMapChaining {
var size: Int //
var capacity: Int //
var loadThres: Double //
var extendRatio: Int //
var buckets: [[Pair]] //
/* */
init() {
size = 0
capacity = 4
loadThres = 2.0 / 3.0
extendRatio = 2
buckets = Array(repeating: [], count: capacity)
}
/* */
func hashFunc(key: Int) -> Int {
key % capacity
}
/* */
func loadFactor() -> Double {
Double(size) / Double(capacity)
}
/* */
func get(key: Int) -> String? {
let index = hashFunc(key: key)
let bucket = buckets[index]
// key val
for pair in bucket {
if pair.key == key {
return pair.val
}
}
// `key` `nil`
return nil
}
/* */
func put(key: Int, val: String) {
//
if loadFactor() > loadThres {
extend()
}
let index = hashFunc(key: key)
let bucket = buckets[index]
// key val
for pair in bucket {
if pair.key == key {
pair.val = val
return
}
}
// key
let pair = Pair(key: key, val: val)
buckets[index].append(pair)
size += 1
}
/* */
func remove(key: Int) {
let index = hashFunc(key: key)
let bucket = buckets[index]
//
for (pairIndex, pair) in bucket.enumerated() {
if pair.key == key {
buckets[index].remove(at: pairIndex)
size -= 1
break
}
}
}
/* */
func extend() {
//
let bucketsTmp = buckets
//
capacity *= extendRatio
buckets = Array(repeating: [], count: capacity)
size = 0
//
for bucket in bucketsTmp {
for pair in bucket {
put(key: pair.key, val: pair.val)
}
}
}
/* */
func print() {
for bucket in buckets {
let res = bucket.map { "\($0.key) -> \($0.val)" }
Swift.print(res)
}
}
}
@main
enum _HashMapChaining {
/* Driver Code */
static func main() {
/* */
let map = HashMapChaining()
/* */
// (key, value)
map.put(key: 12836, val: "シャオハー")
map.put(key: 15937, val: "シャオルオ")
map.put(key: 16750, val: "シャオスワン")
map.put(key: 13276, val: "シャオファー")
map.put(key: 10583, val: "シャオヤー")
print("\n追加完了後のハッシュテーブルは\nKey -> Value")
map.print()
/* */
// key value
let name = map.get(key: 13276)
print("\n学籍番号 13276 を入力すると、名前 \(name!) が見つかりました")
/* */
// (key, value)
map.remove(key: 12836)
print("\n12836 を削除後、ハッシュテーブルは\nKey -> Value")
map.print()
}
}
@@ -0,0 +1,164 @@
/**
* File: hash_map_open_addressing.swift
* Created Time: 2023-06-28
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
/* */
class HashMapOpenAddressing {
var size: Int //
var capacity: Int //
var loadThres: Double //
var extendRatio: Int //
var buckets: [Pair?] //
var TOMBSTONE: Pair //
/* */
init() {
size = 0
capacity = 4
loadThres = 2.0 / 3.0
extendRatio = 2
buckets = Array(repeating: nil, count: capacity)
TOMBSTONE = Pair(key: -1, val: "-1")
}
/* */
func hashFunc(key: Int) -> Int {
key % capacity
}
/* */
func loadFactor() -> Double {
Double(size) / Double(capacity)
}
/* key */
func findBucket(key: Int) -> Int {
var index = hashFunc(key: key)
var firstTombstone = -1
//
while buckets[index] != nil {
// key
if buckets[index]!.key == key {
//
if firstTombstone != -1 {
buckets[firstTombstone] = buckets[index]
buckets[index] = TOMBSTONE
return firstTombstone //
}
return index //
}
//
if firstTombstone == -1 && buckets[index] == TOMBSTONE {
firstTombstone = index
}
//
index = (index + 1) % capacity
}
// key
return firstTombstone == -1 ? index : firstTombstone
}
/* */
func get(key: Int) -> String? {
// key
let index = findBucket(key: key)
// val
if buckets[index] != nil, buckets[index] != TOMBSTONE {
return buckets[index]!.val
}
// null
return nil
}
/* */
func put(key: Int, val: String) {
//
if loadFactor() > loadThres {
extend()
}
// key
let index = findBucket(key: key)
// val
if buckets[index] != nil, buckets[index] != TOMBSTONE {
buckets[index]!.val = val
return
}
//
buckets[index] = Pair(key: key, val: val)
size += 1
}
/* */
func remove(key: Int) {
// key
let index = findBucket(key: key)
//
if buckets[index] != nil, buckets[index] != TOMBSTONE {
buckets[index] = TOMBSTONE
size -= 1
}
}
/* */
func extend() {
//
let bucketsTmp = buckets
//
capacity *= extendRatio
buckets = Array(repeating: nil, count: capacity)
size = 0
//
for pair in bucketsTmp {
if let pair, pair != TOMBSTONE {
put(key: pair.key, val: pair.val)
}
}
}
/* */
func print() {
for pair in buckets {
if pair == nil {
Swift.print("null")
} else if pair == TOMBSTONE {
Swift.print("TOMBSTONE")
} else {
Swift.print("\(pair!.key) -> \(pair!.val)")
}
}
}
}
@main
enum _HashMapOpenAddressing {
/* Driver Code */
static func main() {
/* */
let map = HashMapOpenAddressing()
/* */
// (key, value)
map.put(key: 12836, val: "シャオハー")
map.put(key: 15937, val: "シャオルオ")
map.put(key: 16750, val: "シャオスワン")
map.put(key: 13276, val: "シャオファー")
map.put(key: 10583, val: "シャオヤー")
print("\n追加完了後のハッシュテーブルは\nKey -> Value")
map.print()
/* */
// key value
let name = map.get(key: 13276)
print("\n学籍番号 13276 を入力すると、名前 \(name!) が見つかりました")
/* */
// (key, value)
map.remove(key: 16750)
print("\n16750 を削除後、ハッシュテーブルは\nKey -> Value")
map.print()
}
}
@@ -0,0 +1,73 @@
/**
* File: simple_hash.swift
* Created Time: 2023-07-01
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
func addHash(key: String) -> Int {
var hash = 0
let MODULUS = 1_000_000_007
for c in key {
for scalar in c.unicodeScalars {
hash = (hash + Int(scalar.value)) % MODULUS
}
}
return hash
}
/* */
func mulHash(key: String) -> Int {
var hash = 0
let MODULUS = 1_000_000_007
for c in key {
for scalar in c.unicodeScalars {
hash = (31 * hash + Int(scalar.value)) % MODULUS
}
}
return hash
}
/* XOR */
func xorHash(key: String) -> Int {
var hash = 0
let MODULUS = 1_000_000_007
for c in key {
for scalar in c.unicodeScalars {
hash ^= Int(scalar.value)
}
}
return hash & MODULUS
}
/* */
func rotHash(key: String) -> Int {
var hash = 0
let MODULUS = 1_000_000_007
for c in key {
for scalar in c.unicodeScalars {
hash = ((hash << 4) ^ (hash >> 28) ^ Int(scalar.value)) % MODULUS
}
}
return hash
}
@main
enum SimpleHash {
/* Driver Code */
static func main() {
let key = "Hello アルゴリズム"
var hash = addHash(key: key)
print("加算ハッシュ値は \(hash)")
hash = mulHash(key: key)
print("乗算ハッシュ値は \(hash)")
hash = xorHash(key: key)
print("XORハッシュ値は \(hash)")
hash = rotHash(key: key)
print("回転ハッシュ値は \(hash)")
}
}
+62
View File
@@ -0,0 +1,62 @@
/**
* File: heap.swift
* Created Time: 2024-03-17
* Author: nuomi1 (nuomi1@qq.com)
*/
import HeapModule
import utils
func testPush(heap: inout Heap<Int>, val: Int) {
heap.insert(val)
print("\n要素 \(val) をヒープに追加した後\n")
PrintUtil.printHeap(queue: heap.unordered)
}
func testPop(heap: inout Heap<Int>) {
let val = heap.removeMax()
print("\nヒープ先頭要素 \(val) を取り出した後\n")
PrintUtil.printHeap(queue: heap.unordered)
}
@main
enum _Heap {
/* Driver Code */
static func main() {
/* */
// Swift Heap
var heap = Heap<Int>()
/* */
testPush(heap: &heap, val: 1)
testPush(heap: &heap, val: 3)
testPush(heap: &heap, val: 2)
testPush(heap: &heap, val: 5)
testPush(heap: &heap, val: 4)
/* */
let peek = heap.max()
print("\nヒープ先頭要素は \(peek!)\n")
/* */
testPop(heap: &heap)
testPop(heap: &heap)
testPop(heap: &heap)
testPop(heap: &heap)
testPop(heap: &heap)
/* */
let size = heap.count
print("\nヒープ内の要素数は \(size)\n")
/* */
let isEmpty = heap.isEmpty
print("\nヒープが空かどうか \(isEmpty)\n")
/* */
// O(n) O(nlogn)
let heap2 = Heap([1, 3, 2, 5, 4])
print("\nリストを入力してヒープを構築した後")
PrintUtil.printHeap(queue: heap2.unordered)
}
}
+163
View File
@@ -0,0 +1,163 @@
/**
* File: my_heap.swift
* Created Time: 2023-01-28
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
/* */
class MaxHeap {
private var maxHeap: [Int]
/* */
init(nums: [Int]) {
//
maxHeap = nums
//
for i in (0 ... parent(i: size() - 1)).reversed() {
siftDown(i: i)
}
}
/* */
private func left(i: Int) -> Int {
2 * i + 1
}
/* */
private func right(i: Int) -> Int {
2 * i + 2
}
/* */
private func parent(i: Int) -> Int {
(i - 1) / 2 //
}
/* */
private func swap(i: Int, j: Int) {
maxHeap.swapAt(i, j)
}
/* */
func size() -> Int {
maxHeap.count
}
/* */
func isEmpty() -> Bool {
size() == 0
}
/* */
func peek() -> Int {
maxHeap[0]
}
/* */
func push(val: Int) {
//
maxHeap.append(val)
//
siftUp(i: size() - 1)
}
/* i */
private func siftUp(i: Int) {
var i = i
while true {
// i
let p = parent(i: i)
//
if p < 0 || maxHeap[i] <= maxHeap[p] {
break
}
// 2
swap(i: i, j: p)
//
i = p
}
}
/* */
func pop() -> Int {
//
if isEmpty() {
fatalError("ヒープが空です")
}
//
swap(i: 0, j: size() - 1)
//
let val = maxHeap.remove(at: size() - 1)
//
siftDown(i: 0)
//
return val
}
/* i */
private func siftDown(i: Int) {
var i = i
while true {
// i, l, r ma
let l = left(i: i)
let r = right(i: i)
var ma = i
if l < size(), maxHeap[l] > maxHeap[ma] {
ma = l
}
if r < size(), maxHeap[r] > maxHeap[ma] {
ma = r
}
// i l, r
if ma == i {
break
}
// 2
swap(i: i, j: ma)
//
i = ma
}
}
/* */
func print() {
let queue = maxHeap
PrintUtil.printHeap(queue: queue)
}
}
@main
enum MyHeap {
/* Driver Code */
static func main() {
/* */
let maxHeap = MaxHeap(nums: [9, 8, 6, 6, 7, 5, 2, 1, 4, 3, 6, 2])
print("\nリストを入力してヒープを構築した後")
maxHeap.print()
/* */
var peek = maxHeap.peek()
print("\nヒープ先頭要素は \(peek)")
/* */
let val = 7
maxHeap.push(val: val)
print("\n要素 \(val) をヒープに追加した後")
maxHeap.print()
/* */
peek = maxHeap.pop()
print("\nヒープ先頭要素 \(peek) を取り出した後")
maxHeap.print()
/* */
let size = maxHeap.size()
print("\nヒープ内の要素数は \(size)")
/* */
let isEmpty = maxHeap.isEmpty()
print("\nヒープが空かどうか \(isEmpty)")
}
}
+36
View File
@@ -0,0 +1,36 @@
/**
* File: top_k.swift
* Created Time: 2023-07-02
* Author: nuomi1 (nuomi1@qq.com)
*/
import HeapModule
import utils
/* k */
func topKHeap(nums: [Int], k: Int) -> [Int] {
// k
var heap = Heap(nums.prefix(k))
// k+1 k
for i in nums.indices.dropFirst(k) {
//
if nums[i] > heap.min()! {
_ = heap.removeMin()
heap.insert(nums[i])
}
}
return heap.unordered
}
@main
enum TopK {
/* Driver Code */
static func main() {
let nums = [1, 7, 6, 3, 2]
let k = 3
let res = topKHeap(nums: nums, k: k)
print("最大の \(k) 個の要素は")
PrintUtil.printHeap(queue: res)
}
}
@@ -0,0 +1,62 @@
/**
* File: binary_search.swift
* Created Time: 2023-01-28
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
func binarySearch(nums: [Int], target: Int) -> Int {
// [0, n-1] i, j
var i = nums.startIndex
var j = nums.endIndex - 1
// i > j
while i <= j {
let m = i + (j - i) / 2 // m
if nums[m] < target { // target [m+1, j]
i = m + 1
} else if nums[m] > target { // target [i, m-1]
j = m - 1
} else { //
return m
}
}
// -1
return -1
}
/* */
func binarySearchLCRO(nums: [Int], target: Int) -> Int {
// [0, n) i, j +1
var i = nums.startIndex
var j = nums.endIndex
// i = j
while i < j {
let m = i + (j - i) / 2 // m
if nums[m] < target { // target [m+1, j)
i = m + 1
} else if nums[m] > target { // target [i, m)
j = m
} else { //
return m
}
}
// -1
return -1
}
@main
enum BinarySearch {
/* Driver Code */
static func main() {
let target = 6
let nums = [1, 3, 6, 8, 12, 15, 23, 26, 31, 35]
/* */
var index = binarySearch(nums: nums, target: target)
print("対象要素 6 のインデックス = \(index)")
/* */
index = binarySearchLCRO(nums: nums, target: target)
print("対象要素 6 のインデックス = \(index)")
}
}
@@ -0,0 +1,51 @@
/**
* File: binary_search_edge.swift
* Created Time: 2023-08-06
* Author: nuomi1 (nuomi1@qq.com)
*/
import binary_search_insertion_target
/* target */
func binarySearchLeftEdge(nums: [Int], target: Int) -> Int {
// target
let i = binarySearchInsertion(nums: nums, target: target)
// target -1
if i == nums.endIndex || nums[i] != target {
return -1
}
// target i
return i
}
/* target */
func binarySearchRightEdge(nums: [Int], target: Int) -> Int {
// target + 1
let i = binarySearchInsertion(nums: nums, target: target + 1)
// j target i target
let j = i - 1
// target -1
if j == -1 || nums[j] != target {
return -1
}
// target j
return j
}
@main
enum BinarySearchEdge {
/* Driver Code */
static func main() {
//
let nums = [1, 3, 6, 6, 6, 6, 6, 10, 12, 15]
print("\n配列 nums = \(nums)")
//
for target in [6, 7] {
var index = binarySearchLeftEdge(nums: nums, target: target)
print("最も左にある要素 \(target) のインデックスは \(index)")
index = binarySearchRightEdge(nums: nums, target: target)
print("最も右にある要素 \(target) のインデックスは \(index)")
}
}
}
@@ -0,0 +1,71 @@
/**
* File: binary_search_insertion.swift
* Created Time: 2023-08-06
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
func binarySearchInsertionSimple(nums: [Int], target: Int) -> Int {
// [0, n-1]
var i = nums.startIndex
var j = nums.endIndex - 1
while i <= j {
let m = i + (j - i) / 2 // m
if nums[m] < target {
i = m + 1 // target [m+1, j]
} else if nums[m] > target {
j = m - 1 // target [i, m-1]
} else {
return m // target m
}
}
// target i
return i
}
/* */
public func binarySearchInsertion(nums: [Int], target: Int) -> Int {
// [0, n-1]
var i = nums.startIndex
var j = nums.endIndex - 1
while i <= j {
let m = i + (j - i) / 2 // m
if nums[m] < target {
i = m + 1 // target [m+1, j]
} else if nums[m] > target {
j = m - 1 // target [i, m-1]
} else {
j = m - 1 // target [i, m-1]
}
}
// i
return i
}
#if !TARGET
@main
enum BinarySearchInsertion {
/* Driver Code */
static func main() {
//
var nums = [1, 3, 6, 8, 12, 15, 23, 26, 31, 35]
print("\n配列 nums = \(nums)")
//
for target in [6, 9] {
let index = binarySearchInsertionSimple(nums: nums, target: target)
print("要素 \(target) の挿入位置のインデックスは \(index)")
}
//
nums = [1, 3, 6, 6, 6, 6, 6, 10, 12, 15]
print("\n配列 nums = \(nums)")
//
for target in [2, 6, 20] {
let index = binarySearchInsertion(nums: nums, target: target)
print("要素 \(target) の挿入位置のインデックスは \(index)")
}
}
}
#endif
@@ -0,0 +1,71 @@
/**
* File: binary_search_insertion.swift
* Created Time: 2023-08-06
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
func binarySearchInsertionSimple(nums: [Int], target: Int) -> Int {
// [0, n-1]
var i = nums.startIndex
var j = nums.endIndex - 1
while i <= j {
let m = i + (j - i) / 2 // m
if nums[m] < target {
i = m + 1 // target [m+1, j]
} else if nums[m] > target {
j = m - 1 // target [i, m-1]
} else {
return m // target m
}
}
// target i
return i
}
/* */
public func binarySearchInsertion(nums: [Int], target: Int) -> Int {
// [0, n-1]
var i = nums.startIndex
var j = nums.endIndex - 1
while i <= j {
let m = i + (j - i) / 2 // m
if nums[m] < target {
i = m + 1 // target [m+1, j]
} else if nums[m] > target {
j = m - 1 // target [i, m-1]
} else {
j = m - 1 // target [i, m-1]
}
}
// i
return i
}
#if !TARGET
@main
enum BinarySearchInsertion {
/* Driver Code */
static func main() {
//
var nums = [1, 3, 6, 8, 12, 15, 23, 26, 31, 35]
print("\n配列 nums = \(nums)")
//
for target in [6, 9] {
let index = binarySearchInsertionSimple(nums: nums, target: target)
print("要素 \(target) の挿入位置のインデックスは \(index)")
}
//
nums = [1, 3, 6, 6, 6, 6, 6, 10, 12, 15]
print("\n配列 nums = \(nums)")
//
for target in [2, 6, 20] {
let index = binarySearchInsertion(nums: nums, target: target)
print("要素 \(target) の挿入位置のインデックスは \(index)")
}
}
}
#endif
@@ -0,0 +1,50 @@
/**
* File: hashing_search.swift
* Created Time: 2023-01-28
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
/* */
func hashingSearchArray(map: [Int: Int], target: Int) -> Int {
// key: value:
// key -1
return map[target, default: -1]
}
/* */
func hashingSearchLinkedList(map: [Int: ListNode], target: Int) -> ListNode? {
// key: value:
// key null
return map[target]
}
@main
enum HashingSearch {
/* Driver Code */
static func main() {
let target = 3
/* */
let nums = [1, 5, 3, 2, 4, 7, 5, 9, 10, 8]
//
var map: [Int: Int] = [:]
for i in nums.indices {
map[nums[i]] = i // key: value:
}
let index = hashingSearchArray(map: map, target: target)
print("目標要素 3 のインデックス = \(index)")
/* */
var head = ListNode.arrToLinkedList(arr: nums)
//
var map1: [Int: ListNode] = [:]
while head != nil {
map1[head!.val] = head! // key: value:
head = head?.next
}
let node = hashingSearchLinkedList(map: map1, target: target)
print("目標ノード値 3 に対応するノードオブジェクトは \(node!)")
}
}
@@ -0,0 +1,53 @@
/**
* File: linear_search.swift
* Created Time: 2023-01-28
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
/* */
func linearSearchArray(nums: [Int], target: Int) -> Int {
//
for i in nums.indices {
//
if nums[i] == target {
return i
}
}
// -1
return -1
}
/* */
func linearSearchLinkedList(head: ListNode?, target: Int) -> ListNode? {
var head = head
//
while head != nil {
//
if head?.val == target {
return head
}
head = head?.next
}
// null
return nil
}
@main
enum LinearSearch {
/* Driver Code */
static func main() {
let target = 3
/* */
let nums = [1, 5, 3, 2, 4, 7, 5, 9, 10, 8]
let index = linearSearchArray(nums: nums, target: target)
print("目標要素 3 のインデックス = \(index)")
/* */
let head = ListNode.arrToLinkedList(arr: nums)
let node = linearSearchLinkedList(head: head, target: target)
print("目標ノード値 3 に対応するノードオブジェクトは \(node!)")
}
}
@@ -0,0 +1,49 @@
/**
* File: two_sum.swift
* Created Time: 2023-01-03
* Author: nuomi1 (nuomi1@qq.com)
*/
/* 1 */
func twoSumBruteForce(nums: [Int], target: Int) -> [Int] {
// 2 O(n^2)
for i in nums.indices.dropLast() {
for j in nums.indices.dropFirst(i + 1) {
if nums[i] + nums[j] == target {
return [i, j]
}
}
}
return [0]
}
/* 2 */
func twoSumHashTable(nums: [Int], target: Int) -> [Int] {
// 使 O(n)
var dic: [Int: Int] = [:]
// O(n)
for i in nums.indices {
if let j = dic[target - nums[i]] {
return [j, i]
}
dic[nums[i]] = i
}
return [0]
}
@main
enum LeetcodeTwoSum {
/* Driver Code */
static func main() {
// ======= Test Case =======
let nums = [2, 7, 11, 15]
let target = 13
// ====== Driver Code ======
// 1
var res = twoSumBruteForce(nums: nums, target: target)
print("方法1 res = \(res)")
// 2
res = twoSumHashTable(nums: nums, target: target)
print("方法2 res = \(res)")
}
}
@@ -0,0 +1,51 @@
/**
* File: bubble_sort.swift
* Created Time: 2023-01-29
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
func bubbleSort(nums: inout [Int]) {
// [0, i]
for i in nums.indices.dropFirst().reversed() {
// [0, i]
for j in 0 ..< i {
if nums[j] > nums[j + 1] {
// nums[j] nums[j + 1]
nums.swapAt(j, j + 1)
}
}
}
}
/* */
func bubbleSortWithFlag(nums: inout [Int]) {
// [0, i]
for i in nums.indices.dropFirst().reversed() {
var flag = false //
for j in 0 ..< i {
if nums[j] > nums[j + 1] {
// nums[j] nums[j + 1]
nums.swapAt(j, j + 1)
flag = true //
}
}
if !flag { //
break
}
}
}
@main
enum BubbleSort {
/* Driver Code */
static func main() {
var nums = [4, 1, 3, 1, 5, 2]
bubbleSort(nums: &nums)
print("バブルソート完了後 nums = \(nums)")
var nums1 = [4, 1, 3, 1, 5, 2]
bubbleSortWithFlag(nums: &nums1)
print("バブルソート完了後 nums1 = \(nums1)")
}
}
@@ -0,0 +1,43 @@
/**
* File: bucket_sort.swift
* Created Time: 2023-03-27
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
func bucketSort(nums: inout [Double]) {
// k = n/2 2
let k = nums.count / 2
var buckets = (0 ..< k).map { _ in [Double]() }
// 1.
for num in nums {
// [0, 1) num * k [0, k-1]
let i = Int(num * Double(k))
// num i
buckets[i].append(num)
}
// 2.
for i in buckets.indices {
// 使
buckets[i].sort()
}
// 3.
var i = nums.startIndex
for bucket in buckets {
for num in bucket {
nums[i] = num
i += 1
}
}
}
@main
enum BucketSort {
/* Driver Code */
static func main() {
// [0, 1)
var nums = [0.49, 0.96, 0.82, 0.09, 0.57, 0.43, 0.91, 0.75, 0.15, 0.37]
bucketSort(nums: &nums)
print("バケットソート完了後 nums = \(nums)")
}
}
@@ -0,0 +1,70 @@
/**
* File: counting_sort.swift
* Created Time: 2023-03-22
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
// 使
func countingSortNaive(nums: inout [Int]) {
// 1. m
let m = nums.max()!
// 2.
// counter[num] num
var counter = Array(repeating: 0, count: m + 1)
for num in nums {
counter[num] += 1
}
// 3. counter nums
var i = 0
for num in 0 ..< m + 1 {
for _ in 0 ..< counter[num] {
nums[i] = num
i += 1
}
}
}
/* */
//
func countingSort(nums: inout [Int]) {
// 1. m
let m = nums.max()!
// 2.
// counter[num] num
var counter = Array(repeating: 0, count: m + 1)
for num in nums {
counter[num] += 1
}
// 3. counter
// counter[num]-1 num res
for i in 0 ..< m {
counter[i + 1] += counter[i]
}
// 4. nums res
// res
var res = Array(repeating: 0, count: nums.count)
for i in nums.indices.reversed() {
let num = nums[i]
res[counter[num] - 1] = num // num
counter[num] -= 1 // 1 num
}
// res nums
for i in nums.indices {
nums[i] = res[i]
}
}
@main
enum CountingSort {
/* Driver Code */
static func main() {
var nums = [1, 0, 1, 2, 0, 4, 0, 2, 2, 4]
countingSortNaive(nums: &nums)
print("カウントソート(オブジェクトはソート不可)完了後 nums = \(nums)")
var nums1 = [1, 0, 1, 2, 0, 4, 0, 2, 2, 4]
countingSort(nums: &nums1)
print("カウントソート完了後 nums1 = \(nums1)")
}
}
@@ -0,0 +1,55 @@
/**
* File: heap_sort.swift
* Created Time: 2023-05-28
* Author: nuomi1 (nuomi1@qq.com)
*/
/* n i */
func siftDown(nums: inout [Int], n: Int, i: Int) {
var i = i
while true {
// i, l, r ma
let l = 2 * i + 1
let 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
}
// i l, r
if ma == i {
break
}
// 2
nums.swapAt(i, ma)
//
i = ma
}
}
/* */
func heapSort(nums: inout [Int]) {
//
for i in stride(from: nums.count / 2 - 1, through: 0, by: -1) {
siftDown(nums: &nums, n: nums.count, i: i)
}
// n-1
for i in nums.indices.dropFirst().reversed() {
//
nums.swapAt(0, i)
//
siftDown(nums: &nums, n: i, i: 0)
}
}
@main
enum HeapSort {
/* Driver Code */
static func main() {
var nums = [4, 1, 3, 1, 5, 2]
heapSort(nums: &nums)
print("ヒープソート完了後 nums = \(nums)")
}
}
@@ -0,0 +1,30 @@
/**
* File: insertion_sort.swift
* Created Time: 2023-01-29
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
func insertionSort(nums: inout [Int]) {
// [0, i-1]
for i in nums.indices.dropFirst() {
let base = nums[i]
var j = i - 1
// : base [0, i-1]
while j >= 0, nums[j] > base {
nums[j + 1] = nums[j] // nums[j] 1
j -= 1
}
nums[j + 1] = base // base
}
}
@main
enum InsertionSort {
/* Driver Code */
static func main() {
var nums = [4, 1, 3, 1, 5, 2]
insertionSort(nums: &nums)
print("挿入ソート完了後 nums = \(nums)")
}
}
@@ -0,0 +1,65 @@
/**
* File: merge_sort.swift
* Created Time: 2023-01-29
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
func merge(nums: inout [Int], left: Int, mid: Int, right: Int) {
// [left, mid] [mid+1, right]
// tmp
var tmp = Array(repeating: 0, count: right - left + 1)
//
var i = left, j = mid + 1, k = 0
//
while i <= mid, j <= right {
if nums[i] <= nums[j] {
tmp[k] = nums[i]
i += 1
} else {
tmp[k] = nums[j]
j += 1
}
k += 1
}
//
while i <= mid {
tmp[k] = nums[i]
i += 1
k += 1
}
while j <= right {
tmp[k] = nums[j]
j += 1
k += 1
}
// tmp nums
for k in tmp.indices {
nums[left + k] = tmp[k]
}
}
/* */
func mergeSort(nums: inout [Int], left: Int, right: Int) {
//
if left >= right { // 1
return
}
//
let mid = left + (right - left) / 2 //
mergeSort(nums: &nums, left: left, right: mid) //
mergeSort(nums: &nums, left: mid + 1, right: right) //
//
merge(nums: &nums, left: left, mid: mid, right: right)
}
@main
enum MergeSort {
/* Driver Code */
static func main() {
/* */
var nums = [7, 3, 2, 6, 0, 1, 5, 4]
mergeSort(nums: &nums, left: nums.startIndex, right: nums.endIndex - 1)
print("マージソート完了後 nums = \(nums)")
}
}
@@ -0,0 +1,114 @@
/**
* File: quick_sort.swift
* Created Time: 2023-01-29
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
/* */
func partition(nums: inout [Int], left: Int, right: Int) -> Int {
// nums[left]
var i = left
var j = right
while i < j {
while i < j, nums[j] >= nums[left] {
j -= 1 //
}
while i < j, nums[i] <= nums[left] {
i += 1 //
}
nums.swapAt(i, j) // 2
}
nums.swapAt(i, left) // 2
return i //
}
/* */
func quickSort(nums: inout [Int], left: Int, right: Int) {
// 1
if left >= right {
return
}
//
let pivot = partition(nums: &nums, left: left, right: right)
//
quickSort(nums: &nums, left: left, right: pivot - 1)
quickSort(nums: &nums, left: pivot + 1, right: right)
}
/* */
/* 3 */
func medianThree(nums: [Int], left: Int, mid: Int, right: Int) -> Int {
let l = nums[left]
let m = nums[mid]
let r = nums[right]
if (l <= m && m <= r) || (r <= m && m <= l) {
return mid // m l r
}
if (m <= l && l <= r) || (r <= l && l <= m) {
return left // l m r
}
return right
}
/* 3 */
func partitionMedian(nums: inout [Int], left: Int, right: Int) -> Int {
// 3
let med = medianThree(nums: nums, left: left, mid: left + (right - left) / 2, right: right)
//
nums.swapAt(left, med)
return partition(nums: &nums, left: left, right: right)
}
/* */
func quickSortMedian(nums: inout [Int], left: Int, right: Int) {
// 1
if left >= right {
return
}
//
let pivot = partitionMedian(nums: &nums, left: left, right: right)
//
quickSortMedian(nums: &nums, left: left, right: pivot - 1)
quickSortMedian(nums: &nums, left: pivot + 1, right: right)
}
/* */
func quickSortTailCall(nums: inout [Int], left: Int, right: Int) {
var left = left
var right = right
// 1
while left < right {
//
let pivot = partition(nums: &nums, left: left, right: right)
// 2
if (pivot - left) < (right - pivot) {
quickSortTailCall(nums: &nums, left: left, right: pivot - 1) //
left = pivot + 1 // [pivot + 1, right]
} else {
quickSortTailCall(nums: &nums, left: pivot + 1, right: right) //
right = pivot - 1 // [left, pivot - 1]
}
}
}
@main
enum QuickSort {
/* Driver Code */
static func main() {
/* */
var nums = [2, 4, 1, 0, 3, 5]
quickSort(nums: &nums, left: nums.startIndex, right: nums.endIndex - 1)
print("クイックソート完了後 nums = \(nums)")
/* */
var nums1 = [2, 4, 1, 0, 3, 5]
quickSortMedian(nums: &nums1, left: nums1.startIndex, right: nums1.endIndex - 1)
print("クイックソート(中央値ピボット最適化)完了後 nums1 = \(nums1)")
/* */
var nums2 = [2, 4, 1, 0, 3, 5]
quickSortTailCall(nums: &nums2, left: nums2.startIndex, right: nums2.endIndex - 1)
print("クイックソート(再帰深度最適化)完了後 nums2 = \(nums2)")
}
}
@@ -0,0 +1,79 @@
/**
* File: radix_sort.swift
* Created Time: 2023-01-29
* Author: nuomi1 (nuomi1@qq.com)
*/
/* num k exp = 10^(k-1) */
func digit(num: Int, exp: Int) -> Int {
// k exp
(num / exp) % 10
}
/* nums k */
func countingSortDigit(nums: inout [Int], exp: Int) {
// 10 0~9 10
var counter = Array(repeating: 0, count: 10)
// 0~9
for i in nums.indices {
let d = digit(num: nums[i], exp: exp) // nums[i] k d
counter[d] += 1 // d
}
//
for i in 1 ..< 10 {
counter[i] += counter[i - 1]
}
// res
var res = Array(repeating: 0, count: nums.count)
for i in nums.indices.reversed() {
let d = digit(num: nums[i], exp: exp)
let j = counter[d] - 1 // d j
res[j] = nums[i] // j
counter[d] -= 1 // d 1
}
// nums
for i in nums.indices {
nums[i] = res[i]
}
}
/* */
func radixSort(nums: inout [Int]) {
//
var m = Int.min
for num in nums {
if num > m {
m = num
}
}
//
for exp in sequence(first: 1, next: { m >= ($0 * 10) ? $0 * 10 : nil }) {
// k
// k = 1 -> exp = 1
// k = 2 -> exp = 10
// exp = 10^(k-1)
countingSortDigit(nums: &nums, exp: exp)
}
}
@main
enum RadixSort {
/* Driver Code */
static func main() {
//
var nums = [
10_546_151,
35_663_510,
42_865_989,
34_862_445,
81_883_077,
88_906_420,
72_429_244,
30_524_779,
82_060_337,
63_832_996,
]
radixSort(nums: &nums)
print("基数ソート完了後 nums = \(nums)")
}
}
@@ -0,0 +1,31 @@
/**
* File: selection_sort.swift
* Created Time: 2023-05-28
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
func selectionSort(nums: inout [Int]) {
// [i, n-1]
for i in nums.indices.dropLast() {
//
var k = i
for j in nums.indices.dropFirst(i + 1) {
if nums[j] < nums[k] {
k = j //
}
}
//
nums.swapAt(i, k)
}
}
@main
enum SelectionSort {
/* Driver Code */
static func main() {
var nums = [4, 1, 3, 1, 5, 2]
selectionSort(nums: &nums)
print("選択ソート完了後 nums = \(nums)")
}
}
@@ -0,0 +1,148 @@
/**
* File: array_deque.swift
* Created Time: 2023-02-22
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
class ArrayDeque {
private var nums: [Int] //
private var front: Int //
private var _size: Int //
/* */
init(capacity: Int) {
nums = Array(repeating: 0, count: capacity)
front = 0
_size = 0
}
/* */
func capacity() -> Int {
nums.count
}
/* */
func size() -> Int {
_size
}
/* */
func isEmpty() -> Bool {
size() == 0
}
/* */
private func index(i: Int) -> Int {
//
// i
// i
(i + capacity()) % capacity()
}
/* */
func pushFirst(num: Int) {
if size() == capacity() {
print("両端キューがいっぱいです")
return
}
// 1
// front
front = index(i: front - 1)
// num
nums[front] = num
_size += 1
}
/* */
func pushLast(num: Int) {
if size() == capacity() {
print("両端キューがいっぱいです")
return
}
// + 1
let rear = index(i: front + size())
// num
nums[rear] = num
_size += 1
}
/* */
func popFirst() -> Int {
let num = peekFirst()
// 1
front = index(i: front + 1)
_size -= 1
return num
}
/* */
func popLast() -> Int {
let num = peekLast()
_size -= 1
return num
}
/* */
func peekFirst() -> Int {
if isEmpty() {
fatalError("両端キューが空です")
}
return nums[front]
}
/* */
func peekLast() -> Int {
if isEmpty() {
fatalError("両端キューが空です")
}
//
let last = index(i: front + size() - 1)
return nums[last]
}
/* */
func toArray() -> [Int] {
//
(front ..< front + size()).map { nums[index(i: $0)] }
}
}
@main
enum _ArrayDeque {
/* Driver Code */
static func main() {
/* */
let deque = ArrayDeque(capacity: 10)
deque.pushLast(num: 3)
deque.pushLast(num: 2)
deque.pushLast(num: 5)
print("両端キュー deque = \(deque.toArray())")
/* */
let peekFirst = deque.peekFirst()
print("先頭要素 peekFirst = \(peekFirst)")
let peekLast = deque.peekLast()
print("末尾要素 peekLast = \(peekLast)")
/* */
deque.pushLast(num: 4)
print("要素 4 を末尾に追加した後 deque = \(deque.toArray())")
deque.pushFirst(num: 1)
print("要素 1 を先頭に追加した後 deque = \(deque.toArray())")
/* */
let popLast = deque.popLast()
print("末尾から取り出した要素 = \(popLast),末尾から取り出した後 deque = \(deque.toArray())")
let popFirst = deque.popFirst()
print("先頭から取り出した要素 = \(popFirst),先頭から取り出した後 deque = \(deque.toArray())")
/* */
let size = deque.size()
print("両端キューのサイズ size = \(size)")
/* */
let isEmpty = deque.isEmpty()
print("両端キューが空かどうか = \(isEmpty)")
}
}
@@ -0,0 +1,113 @@
/**
* File: array_queue.swift
* Created Time: 2023-01-11
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
class ArrayQueue {
private var nums: [Int] //
private var front: Int //
private var _size: Int //
init(capacity: Int) {
//
nums = Array(repeating: 0, count: capacity)
front = 0
_size = 0
}
/* */
func capacity() -> Int {
nums.count
}
/* */
func size() -> Int {
_size
}
/* */
func isEmpty() -> Bool {
size() == 0
}
/* */
func push(num: Int) {
if size() == capacity() {
print("キューがいっぱいです")
return
}
// + 1
// rear
let rear = (front + size()) % capacity()
// num
nums[rear] = num
_size += 1
}
/* */
@discardableResult
func pop() -> Int {
let num = peek()
// 1
front = (front + 1) % capacity()
_size -= 1
return num
}
/* */
func peek() -> Int {
if isEmpty() {
fatalError("キューが空です")
}
return nums[front]
}
/* */
func toArray() -> [Int] {
//
(front ..< front + size()).map { nums[$0 % capacity()] }
}
}
@main
enum _ArrayQueue {
/* Driver Code */
static func main() {
/* */
let capacity = 10
let queue = ArrayQueue(capacity: capacity)
/* */
queue.push(num: 1)
queue.push(num: 3)
queue.push(num: 2)
queue.push(num: 5)
queue.push(num: 4)
print("キュー queue = \(queue.toArray())")
/* */
let peek = queue.peek()
print("先頭要素 peek = \(peek)")
/* */
let pop = queue.pop()
print("取り出した要素 pop = \(pop),取り出し後 queue = \(queue.toArray())")
/* */
let size = queue.size()
print("キューのサイズ size = \(size)")
/* */
let isEmpty = queue.isEmpty()
print("キューが空かどうか = \(isEmpty)")
/* */
for i in 0 ..< 10 {
queue.push(num: i)
queue.pop()
print("\(i) 回のエンキュー + デキュー後 queue = \(queue.toArray())")
}
}
}
@@ -0,0 +1,85 @@
/**
* File: array_stack.swift
* Created Time: 2023-01-09
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
class ArrayStack {
private var stack: [Int]
init() {
//
stack = []
}
/* */
func size() -> Int {
stack.count
}
/* */
func isEmpty() -> Bool {
stack.isEmpty
}
/* */
func push(num: Int) {
stack.append(num)
}
/* */
@discardableResult
func pop() -> Int {
if isEmpty() {
fatalError("スタックが空です")
}
return stack.removeLast()
}
/* */
func peek() -> Int {
if isEmpty() {
fatalError("スタックが空です")
}
return stack.last!
}
/* List Array */
func toArray() -> [Int] {
stack
}
}
@main
enum _ArrayStack {
/* Driver Code */
static func main() {
/* */
let stack = ArrayStack()
/* */
stack.push(num: 1)
stack.push(num: 3)
stack.push(num: 2)
stack.push(num: 5)
stack.push(num: 4)
print("スタック stack = \(stack.toArray())")
/* */
let peek = stack.peek()
print("スタックトップ要素 peek = \(peek)")
/* */
let pop = stack.pop()
print("ポップした要素 pop = \(pop)、ポップ後の stack = \(stack.toArray())")
/* */
let size = stack.size()
print("スタックの長さ size = \(size)")
/* */
let isEmpty = stack.isEmpty()
print("スタックが空かどうか = \(isEmpty)")
}
}
@@ -0,0 +1,44 @@
/**
* File: deque.swift
* Created Time: 2023-01-14
* Author: nuomi1 (nuomi1@qq.com)
*/
@main
enum Deque {
/* Driver Code */
static func main() {
/* */
// Swift Array 使
var deque: [Int] = []
/* */
deque.append(2)
deque.append(5)
deque.append(4)
deque.insert(3, at: 0)
deque.insert(1, at: 0)
print("両端キュー deque = \(deque)")
/* */
let peekFirst = deque.first!
print("先頭要素 peekFirst = \(peekFirst)")
let peekLast = deque.last!
print("末尾要素 peekLast = \(peekLast)")
/* */
// Array popFirst O(n)
let popFirst = deque.removeFirst()
print("先頭からデキューした要素 popFirst = \(popFirst)、先頭からデキュー後の deque = \(deque)")
let popLast = deque.removeLast()
print("末尾からデキューした要素 popLast = \(popLast)、末尾からデキュー後の deque = \(deque)")
/* */
let size = deque.count
print("両端キューのサイズ size = \(size)")
/* */
let isEmpty = deque.isEmpty
print("両端キューが空かどうか = \(isEmpty)")
}
}
@@ -0,0 +1,180 @@
/**
* File: linkedlist_deque.swift
* Created Time: 2023-02-22
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
class ListNode {
var val: Int //
var next: ListNode? //
weak var prev: ListNode? //
init(val: Int) {
self.val = val
}
}
/* */
class LinkedListDeque {
private var front: ListNode? // front
private var rear: ListNode? // rear
private var _size: Int //
init() {
_size = 0
}
/* */
func size() -> Int {
_size
}
/* */
func isEmpty() -> Bool {
size() == 0
}
/* */
private func push(num: Int, isFront: Bool) {
let node = ListNode(val: num)
// front rear node
if isEmpty() {
front = node
rear = node
}
//
else if isFront {
// node
front?.prev = node
node.next = front
front = node //
}
//
else {
// node
rear?.next = node
node.prev = rear
rear = node //
}
_size += 1 //
}
/* */
func pushFirst(num: Int) {
push(num: num, isFront: true)
}
/* */
func pushLast(num: Int) {
push(num: num, isFront: false)
}
/* */
private func pop(isFront: Bool) -> Int {
if isEmpty() {
fatalError("両端キューが空です")
}
let val: Int
//
if isFront {
val = front!.val //
//
let fNext = front?.next
if fNext != nil {
fNext?.prev = nil
front?.next = nil
}
front = fNext //
}
//
else {
val = rear!.val //
//
let rPrev = rear?.prev
if rPrev != nil {
rPrev?.next = nil
rear?.prev = nil
}
rear = rPrev //
}
_size -= 1 //
return val
}
/* */
func popFirst() -> Int {
pop(isFront: true)
}
/* */
func popLast() -> Int {
pop(isFront: false)
}
/* */
func peekFirst() -> Int {
if isEmpty() {
fatalError("両端キューが空です")
}
return front!.val
}
/* */
func peekLast() -> Int {
if isEmpty() {
fatalError("両端キューが空です")
}
return rear!.val
}
/* */
func toArray() -> [Int] {
var node = front
var res = Array(repeating: 0, count: size())
for i in res.indices {
res[i] = node!.val
node = node?.next
}
return res
}
}
@main
enum _LinkedListDeque {
/* Driver Code */
static func main() {
/* */
let deque = LinkedListDeque()
deque.pushLast(num: 3)
deque.pushLast(num: 2)
deque.pushLast(num: 5)
print("両端キュー deque = \(deque.toArray())")
/* */
let peekFirst = deque.peekFirst()
print("先頭要素 peekFirst = \(peekFirst)")
let peekLast = deque.peekLast()
print("末尾要素 peekLast = \(peekLast)")
/* */
deque.pushLast(num: 4)
print("要素 4 を末尾に追加した後 deque = \(deque.toArray())")
deque.pushFirst(num: 1)
print("要素 1 を先頭に追加した後 deque = \(deque.toArray())")
/* */
let popLast = deque.popLast()
print("末尾から取り出した要素 = \(popLast),末尾から取り出した後 deque = \(deque.toArray())")
let popFirst = deque.popFirst()
print("先頭から取り出した要素 = \(popFirst),先頭から取り出した後 deque = \(deque.toArray())")
/* */
let size = deque.size()
print("両端キューのサイズ size = \(size)")
/* */
let isEmpty = deque.isEmpty()
print("両端キューが空かどうか = \(isEmpty)")
}
}
@@ -0,0 +1,107 @@
/**
* File: linkedlist_queue.swift
* Created Time: 2023-01-11
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
/* */
class LinkedListQueue {
private var front: ListNode? //
private var rear: ListNode? //
private var _size: Int
init() {
_size = 0
}
/* */
func size() -> Int {
_size
}
/* */
func isEmpty() -> Bool {
size() == 0
}
/* */
func push(num: Int) {
// num
let node = ListNode(x: num)
//
if front == nil {
front = node
rear = node
}
//
else {
rear?.next = node
rear = node
}
_size += 1
}
/* */
@discardableResult
func pop() -> Int {
let num = peek()
//
front = front?.next
_size -= 1
return num
}
/* */
func peek() -> Int {
if isEmpty() {
fatalError("キューが空です")
}
return front!.val
}
/* Array */
func toArray() -> [Int] {
var node = front
var res = Array(repeating: 0, count: size())
for i in res.indices {
res[i] = node!.val
node = node?.next
}
return res
}
}
@main
enum _LinkedListQueue {
/* Driver Code */
static func main() {
/* */
let queue = LinkedListQueue()
/* */
queue.push(num: 1)
queue.push(num: 3)
queue.push(num: 2)
queue.push(num: 5)
queue.push(num: 4)
print("キュー queue = \(queue.toArray())")
/* */
let peek = queue.peek()
print("先頭要素 peek = \(peek)")
/* */
let pop = queue.pop()
print("取り出した要素 pop = \(pop),取り出し後 queue = \(queue.toArray())")
/* */
let size = queue.size()
print("キューのサイズ size = \(size)")
/* */
let isEmpty = queue.isEmpty()
print("キューが空かどうか = \(isEmpty)")
}
}
@@ -0,0 +1,96 @@
/**
* File: linkedlist_stack.swift
* Created Time: 2023-01-09
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
/* */
class LinkedListStack {
private var _peek: ListNode? //
private var _size: Int //
init() {
_size = 0
}
/* */
func size() -> Int {
_size
}
/* */
func isEmpty() -> Bool {
size() == 0
}
/* */
func push(num: Int) {
let node = ListNode(x: num)
node.next = _peek
_peek = node
_size += 1
}
/* */
@discardableResult
func pop() -> Int {
let num = peek()
_peek = _peek?.next
_size -= 1
return num
}
/* */
func peek() -> Int {
if isEmpty() {
fatalError("スタックが空です")
}
return _peek!.val
}
/* List Array */
func toArray() -> [Int] {
var node = _peek
var res = Array(repeating: 0, count: size())
for i in res.indices.reversed() {
res[i] = node!.val
node = node?.next
}
return res
}
}
@main
enum _LinkedListStack {
/* Driver Code */
static func main() {
/* */
let stack = LinkedListStack()
/* */
stack.push(num: 1)
stack.push(num: 3)
stack.push(num: 2)
stack.push(num: 5)
stack.push(num: 4)
print("スタック stack = \(stack.toArray())")
/* */
let peek = stack.peek()
print("スタックトップ要素 peek = \(peek)")
/* */
let pop = stack.pop()
print("ポップした要素 pop = \(pop)、ポップ後の stack = \(stack.toArray())")
/* */
let size = stack.size()
print("スタックの長さ size = \(size)")
/* */
let isEmpty = stack.isEmpty()
print("スタックが空かどうか = \(isEmpty)")
}
}
@@ -0,0 +1,40 @@
/**
* File: queue.swift
* Created Time: 2023-01-11
* Author: nuomi1 (nuomi1@qq.com)
*/
@main
enum Queue {
/* Driver Code */
static func main() {
/* */
// Swift Array 使
var queue: [Int] = []
/* */
queue.append(1)
queue.append(3)
queue.append(2)
queue.append(5)
queue.append(4)
print("キュー queue = \(queue)")
/* */
let peek = queue.first!
print("先頭要素 peek = \(peek)")
/* */
// Array pop O(n)
let pool = queue.removeFirst()
print("デキューした要素 pop = \(pool)、デキュー後の queue = \(queue)")
/* */
let size = queue.count
print("キューのサイズ size = \(size)")
/* */
let isEmpty = queue.isEmpty
print("キューが空かどうか = \(isEmpty)")
}
}
@@ -0,0 +1,39 @@
/**
* File: stack.swift
* Created Time: 2023-01-09
* Author: nuomi1 (nuomi1@qq.com)
*/
@main
enum Stack {
/* Driver Code */
static func main() {
/* */
// Swift Array 使
var stack: [Int] = []
/* */
stack.append(1)
stack.append(3)
stack.append(2)
stack.append(5)
stack.append(4)
print("スタック stack = \(stack)")
/* */
let peek = stack.last!
print("スタックトップ要素 peek = \(peek)")
/* */
let pop = stack.removeLast()
print("ポップした要素 pop = \(pop)、ポップ後の stack = \(stack)")
/* */
let size = stack.count
print("スタックの長さ size = \(size)")
/* */
let isEmpty = stack.isEmpty
print("スタックが空かどうか = \(isEmpty)")
}
}
@@ -0,0 +1,141 @@
/**
* File: array_binary_tree.swift
* Created Time: 2023-07-23
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
/* */
class ArrayBinaryTree {
private var tree: [Int?]
/* */
init(arr: [Int?]) {
tree = arr
}
/* */
func size() -> Int {
tree.count
}
/* i */
func val(i: Int) -> Int? {
// null
if i < 0 || i >= size() {
return nil
}
return tree[i]
}
/* i */
func left(i: Int) -> Int {
2 * i + 1
}
/* i */
func right(i: Int) -> Int {
2 * i + 2
}
/* i */
func parent(i: Int) -> Int {
(i - 1) / 2
}
/* */
func levelOrder() -> [Int] {
var res: [Int] = []
//
for i in 0 ..< size() {
if let val = val(i: i) {
res.append(val)
}
}
return res
}
/* */
private func dfs(i: Int, order: String, res: inout [Int]) {
//
guard let val = val(i: i) else {
return
}
//
if order == "pre" {
res.append(val)
}
dfs(i: left(i: i), order: order, res: &res)
//
if order == "in" {
res.append(val)
}
dfs(i: right(i: i), order: order, res: &res)
//
if order == "post" {
res.append(val)
}
}
/* */
func preOrder() -> [Int] {
var res: [Int] = []
dfs(i: 0, order: "pre", res: &res)
return res
}
/* */
func inOrder() -> [Int] {
var res: [Int] = []
dfs(i: 0, order: "in", res: &res)
return res
}
/* */
func postOrder() -> [Int] {
var res: [Int] = []
dfs(i: 0, order: "post", res: &res)
return res
}
}
@main
enum _ArrayBinaryTree {
/* Driver Code */
static func main() {
//
//
let arr = [1, 2, 3, 4, nil, 6, 7, 8, 9, nil, nil, 12, nil, nil, 15]
let root = TreeNode.listToTree(arr: arr)
print("\n二分木を初期化\n")
print("二分木の配列表現:")
print(arr)
print("二分木の連結リスト表現:")
PrintUtil.printTree(root: root)
//
let abt = ArrayBinaryTree(arr: arr)
//
let i = 1
let l = abt.left(i: i)
let r = abt.right(i: i)
let p = abt.parent(i: i)
print("\n現在のノードのインデックスは \(i) 、値は \(abt.val(i: i) as Any)")
print("左の子ノードのインデックスは \(l) 、値は \(abt.val(i: l) as Any)")
print("右の子ノードのインデックスは \(r) 、値は \(abt.val(i: r) as Any)")
print("親ノードのインデックスは \(p) 、値は \(abt.val(i: p) as Any)")
//
var res = abt.levelOrder()
print("\nレベル順走査:\(res)")
res = abt.preOrder()
print("先行順走査:\(res)")
res = abt.inOrder()
print("中間順走査:\(res)")
res = abt.postOrder()
print("後順走査は:\(res)")
}
}
+230
View File
@@ -0,0 +1,230 @@
/**
* File: avl_tree.swift
* Created Time: 2023-01-28
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
/* AVL */
class AVLTree {
fileprivate var root: TreeNode? //
init() {}
/* */
func height(node: TreeNode?) -> Int {
// -1 0
node?.height ?? -1
}
/* */
private func updateHeight(node: TreeNode?) {
// + 1
node?.height = max(height(node: node?.left), height(node: node?.right)) + 1
}
/* */
func balanceFactor(node: TreeNode?) -> Int {
// 0
guard let node = node else { return 0 }
// = -
return height(node: node.left) - height(node: node.right)
}
/* */
private func rightRotate(node: TreeNode?) -> TreeNode? {
let child = node?.left
let grandChild = child?.right
// child node
child?.right = node
node?.left = grandChild
//
updateHeight(node: node)
updateHeight(node: child)
//
return child
}
/* */
private func leftRotate(node: TreeNode?) -> TreeNode? {
let child = node?.right
let grandChild = child?.left
// child node
child?.left = node
node?.right = grandChild
//
updateHeight(node: node)
updateHeight(node: child)
//
return child
}
/* */
private func rotate(node: TreeNode?) -> TreeNode? {
// node
let balanceFactor = balanceFactor(node: node)
//
if balanceFactor > 1 {
if self.balanceFactor(node: node?.left) >= 0 {
//
return rightRotate(node: node)
} else {
//
node?.left = leftRotate(node: node?.left)
return rightRotate(node: node)
}
}
//
if balanceFactor < -1 {
if self.balanceFactor(node: node?.right) <= 0 {
//
return leftRotate(node: node)
} else {
//
node?.right = rightRotate(node: node?.right)
return leftRotate(node: node)
}
}
//
return node
}
/* */
func insert(val: Int) {
root = insertHelper(node: root, val: val)
}
/* */
private func insertHelper(node: TreeNode?, val: Int) -> TreeNode? {
var node = node
if node == nil {
return TreeNode(x: val)
}
/* 1. */
if val < node!.val {
node?.left = insertHelper(node: node?.left, val: val)
} else if val > node!.val {
node?.right = insertHelper(node: node?.right, val: val)
} else {
return node //
}
updateHeight(node: node) //
/* 2. */
node = rotate(node: node)
//
return node
}
/* */
func remove(val: Int) {
root = removeHelper(node: root, val: val)
}
/* */
private func removeHelper(node: TreeNode?, val: Int) -> TreeNode? {
var node = node
if node == nil {
return nil
}
/* 1. */
if val < node!.val {
node?.left = removeHelper(node: node?.left, val: val)
} else if val > node!.val {
node?.right = removeHelper(node: node?.right, val: val)
} else {
if node?.left == nil || node?.right == nil {
let child = node?.left ?? node?.right
// = 0 node
if child == nil {
return nil
}
// = 1 node
else {
node = child
}
} else {
// = 2
var temp = node?.right
while temp?.left != nil {
temp = temp?.left
}
node?.right = removeHelper(node: node?.right, val: temp!.val)
node?.val = temp!.val
}
}
updateHeight(node: node) //
/* 2. */
node = rotate(node: node)
//
return node
}
/* */
func search(val: Int) -> TreeNode? {
var cur = root
while cur != nil {
// cur
if cur!.val < val {
cur = cur?.right
}
// cur
else if cur!.val > val {
cur = cur?.left
}
//
else {
break
}
}
//
return cur
}
}
@main
enum _AVLTree {
static func testInsert(tree: AVLTree, val: Int) {
tree.insert(val: val)
print("\nノード \(val) を挿入後、AVL 木は")
PrintUtil.printTree(root: tree.root)
}
static func testRemove(tree: AVLTree, val: Int) {
tree.remove(val: val)
print("\nノード \(val) を削除後、AVL 木は")
PrintUtil.printTree(root: tree.root)
}
/* Driver Code */
static func main() {
/* AVL */
let avlTree = AVLTree()
/* */
// AVL
testInsert(tree: avlTree, val: 1)
testInsert(tree: avlTree, val: 2)
testInsert(tree: avlTree, val: 3)
testInsert(tree: avlTree, val: 4)
testInsert(tree: avlTree, val: 5)
testInsert(tree: avlTree, val: 8)
testInsert(tree: avlTree, val: 7)
testInsert(tree: avlTree, val: 9)
testInsert(tree: avlTree, val: 10)
testInsert(tree: avlTree, val: 6)
/* */
testInsert(tree: avlTree, val: 7)
/* */
// AVL
testRemove(tree: avlTree, val: 8) // 0
testRemove(tree: avlTree, val: 5) // 1
testRemove(tree: avlTree, val: 4) // 2
/* */
let node = avlTree.search(val: 7)
print("\n見つかったノードオブジェクトは \(node!)、ノード値 = \(node!.val)")
}
}
@@ -0,0 +1,173 @@
/**
* File: binary_search_tree.swift
* Created Time: 2023-01-26
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
/* */
class BinarySearchTree {
private var root: TreeNode?
/* */
init() {
//
root = nil
}
/* */
func getRoot() -> TreeNode? {
root
}
/* */
func search(num: Int) -> TreeNode? {
var cur = root
//
while cur != nil {
// cur
if cur!.val < num {
cur = cur?.right
}
// cur
else if cur!.val > num {
cur = cur?.left
}
//
else {
break
}
}
//
return cur
}
/* */
func insert(num: Int) {
//
if root == nil {
root = TreeNode(x: num)
return
}
var cur = root
var pre: TreeNode?
//
while cur != nil {
//
if cur!.val == num {
return
}
pre = cur
// cur
if cur!.val < num {
cur = cur?.right
}
// cur
else {
cur = cur?.left
}
}
//
let node = TreeNode(x: num)
if pre!.val < num {
pre?.right = node
} else {
pre?.left = node
}
}
/* */
func remove(num: Int) {
//
if root == nil {
return
}
var cur = root
var pre: TreeNode?
//
while cur != nil {
//
if cur!.val == num {
break
}
pre = cur
// cur
if cur!.val < num {
cur = cur?.right
}
// cur
else {
cur = cur?.left
}
}
//
if cur == nil {
return
}
// = 0 or 1
if cur?.left == nil || cur?.right == nil {
// 0 / 1 child = null /
let child = cur?.left ?? cur?.right
// cur
if cur !== root {
if pre?.left === cur {
pre?.left = child
} else {
pre?.right = child
}
} else {
//
root = child
}
}
// = 2
else {
// cur
var tmp = cur?.right
while tmp?.left != nil {
tmp = tmp?.left
}
// tmp
remove(num: tmp!.val)
// tmp cur
cur?.val = tmp!.val
}
}
}
@main
enum _BinarySearchTree {
/* Driver Code */
static func main() {
/* */
let bst = BinarySearchTree()
//
let nums = [8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15]
for num in nums {
bst.insert(num: num)
}
print("\n初期化された二分木は\n")
PrintUtil.printTree(root: bst.getRoot())
/* */
let node = bst.search(num: 7)
print("\n見つかったノードオブジェクトは \(node!)、ノード値 = \(node!.val)")
/* */
bst.insert(num: 16)
print("\nノード 16 を挿入後、二分木は\n")
PrintUtil.printTree(root: bst.getRoot())
/* */
bst.remove(num: 1)
print("\nノード 1 を削除後、二分木は\n")
PrintUtil.printTree(root: bst.getRoot())
bst.remove(num: 2)
print("\nノード 2 を削除後、二分木は\n")
PrintUtil.printTree(root: bst.getRoot())
bst.remove(num: 4)
print("\nノード 4 を削除後、二分木は\n")
PrintUtil.printTree(root: bst.getRoot())
}
}
@@ -0,0 +1,40 @@
/**
* File: binary_tree.swift
* Created Time: 2023-01-18
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
@main
enum BinaryTree {
/* Driver Code */
static func main() {
/* */
//
let n1 = TreeNode(x: 1)
let n2 = TreeNode(x: 2)
let n3 = TreeNode(x: 3)
let n4 = TreeNode(x: 4)
let n5 = TreeNode(x: 5)
//
n1.left = n2
n1.right = n3
n2.left = n4
n2.right = n5
print("\n二分木を初期化\n")
PrintUtil.printTree(root: n1)
/* */
let P = TreeNode(x: 0)
// n1 -> n2 P
n1.left = P
P.left = n2
print("\nノード P を挿入後\n")
PrintUtil.printTree(root: n1)
// P
n1.left = n2
print("\nノード P を削除後\n")
PrintUtil.printTree(root: n1)
}
}
@@ -0,0 +1,42 @@
/**
* File: binary_tree_bfs.swift
* Created Time: 2023-01-18
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
/* */
func levelOrder(root: TreeNode) -> [Int] {
//
var queue: [TreeNode] = [root]
//
var list: [Int] = []
while !queue.isEmpty {
let node = queue.removeFirst() //
list.append(node.val) //
if let left = node.left {
queue.append(left) //
}
if let right = node.right {
queue.append(right) //
}
}
return list
}
@main
enum BinaryTreeBFS {
/* Driver Code */
static func main() {
/* */
//
let node = TreeNode.listToTree(arr: [1, 2, 3, 4, 5, 6, 7])!
print("\n二分木を初期化\n")
PrintUtil.printTree(root: node)
/* */
let list = levelOrder(root: node)
print("\nレベル順走査のノード出力シーケンス = \(list)")
}
}
@@ -0,0 +1,70 @@
/**
* File: binary_tree_dfs.swift
* Created Time: 2023-01-18
* Author: nuomi1 (nuomi1@qq.com)
*/
import utils
//
var list: [Int] = []
/* */
func preOrder(root: TreeNode?) {
guard let root = root else {
return
}
// -> ->
list.append(root.val)
preOrder(root: root.left)
preOrder(root: root.right)
}
/* */
func inOrder(root: TreeNode?) {
guard let root = root else {
return
}
// : -> ->
inOrder(root: root.left)
list.append(root.val)
inOrder(root: root.right)
}
/* */
func postOrder(root: TreeNode?) {
guard let root = root else {
return
}
// : -> ->
postOrder(root: root.left)
postOrder(root: root.right)
list.append(root.val)
}
@main
enum BinaryTreeDFS {
/* Driver Code */
static func main() {
/* */
//
let root = TreeNode.listToTree(arr: [1, 2, 3, 4, 5, 6, 7])!
print("\n二分木を初期化\n")
PrintUtil.printTree(root: root)
/* */
list.removeAll()
preOrder(root: root)
print("\n前順走査のノード出力シーケンス = \(list)")
/* */
list.removeAll()
inOrder(root: root)
print("\n中順走査のノード出力シーケンス = \(list)")
/* */
list.removeAll()
postOrder(root: root)
print("\n後順走査のノード出力シーケンス = \(list)")
}
}
+33
View File
@@ -0,0 +1,33 @@
/**
* File: ListNode.swift
* Created Time: 2023-01-02
* Author: nuomi1 (nuomi1@qq.com)
*/
public class ListNode: Hashable {
public var val: Int //
public var next: ListNode? //
public init(x: Int) {
val = x
}
public static func == (lhs: ListNode, rhs: ListNode) -> Bool {
lhs.val == rhs.val && lhs.next.map { ObjectIdentifier($0) } == rhs.next.map { ObjectIdentifier($0) }
}
public func hash(into hasher: inout Hasher) {
hasher.combine(val)
hasher.combine(next.map { ObjectIdentifier($0) })
}
public static func arrToLinkedList(arr: [Int]) -> ListNode? {
let dum = ListNode(x: 0)
var head: ListNode? = dum
for val in arr {
head?.next = ListNode(x: val)
head = head?.next
}
return dum.next
}
}
+20
View File
@@ -0,0 +1,20 @@
/**
* File: Pair.swift
* Created Time: 2023-06-28
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
public class Pair: Equatable {
public var key: Int
public var val: String
public init(key: Int, val: String) {
self.key = key
self.val = val
}
public static func == (lhs: Pair, rhs: Pair) -> Bool {
lhs.key == rhs.key && lhs.val == rhs.val
}
}
+93
View File
@@ -0,0 +1,93 @@
/**
* File: PrintUtil.swift
* Created Time: 2023-01-02
* Author: nuomi1 (nuomi1@qq.com)
*/
public enum PrintUtil {
private class Trunk {
var prev: Trunk?
var str: String
init(prev: Trunk?, str: String) {
self.prev = prev
self.str = str
}
}
public static func printLinkedList(head: ListNode) {
var head: ListNode? = head
var list: [String] = []
while head != nil {
list.append("\(head!.val)")
head = head?.next
}
print(list.joined(separator: " -> "))
}
public static func printTree(root: TreeNode?) {
printTree(root: root, prev: nil, isRight: false)
}
private static func printTree(root: TreeNode?, prev: Trunk?, isRight: Bool) {
if root == nil {
return
}
var prevStr = " "
let trunk = Trunk(prev: prev, str: prevStr)
printTree(root: root?.right, prev: trunk, isRight: true)
if prev == nil {
trunk.str = "———"
} else if isRight {
trunk.str = "/———"
prevStr = " |"
} else {
trunk.str = "\\———"
prev?.str = prevStr
}
showTrunks(p: trunk)
print(" \(root!.val)")
if prev != nil {
prev?.str = prevStr
}
trunk.str = " |"
printTree(root: root?.left, prev: trunk, isRight: false)
}
private static func showTrunks(p: Trunk?) {
if p == nil {
return
}
showTrunks(p: p?.prev)
print(p!.str, terminator: "")
}
public static func printHashMap<K, V>(map: [K: V]) {
for (key, value) in map {
print("\(key) -> \(value)")
}
}
public static func printHeap(queue: [Int]) {
print("ヒープの配列表現:", terminator: "")
print(queue)
print("ヒープの木構造表現:")
let root = TreeNode.listToTree(arr: queue)
printTree(root: root)
}
public static func printMatrix<T>(matrix: [[T]]) {
print("[")
for row in matrix {
print(" \(row),")
}
print("]")
}
}
+71
View File
@@ -0,0 +1,71 @@
/**
* File: TreeNode.swift
* Created Time: 2023-01-02
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
public class TreeNode {
public var val: Int //
public var height: Int //
public var left: TreeNode? //
public var right: TreeNode? //
/* */
public init(x: Int) {
val = x
height = 0
}
// :
// https://www.hello-algo.com/chapter_tree/array_representation_of_tree/
// :
// [1, 2, 3, 4, nil, 6, 7, 8, 9, nil, nil, 12, nil, nil, 15]
// :
// / 15
// / 7
// / 3
// | \\ 6
// | \\ 12
// 1
// \\ 2
// | / 9
// \\ 4
// \\ 8
/* : */
private static func listToTreeDFS(arr: [Int?], i: Int) -> TreeNode? {
if i < 0 || i >= arr.count || arr[i] == nil {
return nil
}
let root = TreeNode(x: arr[i]!)
root.left = listToTreeDFS(arr: arr, i: 2 * i + 1)
root.right = listToTreeDFS(arr: arr, i: 2 * i + 2)
return root
}
/* */
public static func listToTree(arr: [Int?]) -> TreeNode? {
listToTreeDFS(arr: arr, i: 0)
}
/* : */
private static func treeToListDFS(root: TreeNode?, i: Int, res: inout [Int?]) {
if root == nil {
return
}
while i >= res.count {
res.append(nil)
}
res[i] = root?.val
treeToListDFS(root: root?.left, i: 2 * i + 1, res: &res)
treeToListDFS(root: root?.right, i: 2 * i + 2, res: &res)
}
/* */
public static func treeToList(root: TreeNode?) -> [Int?] {
var res: [Int?] = []
treeToListDFS(root: root, i: 0, res: &res)
return res
}
}
+32
View File
@@ -0,0 +1,32 @@
/**
* File: Vertex.swift
* Created Time: 2023-02-19
* Author: nuomi1 (nuomi1@qq.com)
*/
/* */
public class Vertex: Hashable {
public var val: Int
public init(val: Int) {
self.val = val
}
public static func == (lhs: Vertex, rhs: Vertex) -> Bool {
lhs.val == rhs.val
}
public func hash(into hasher: inout Hasher) {
hasher.combine(val)
}
/* vals vets */
public static func valsToVets(vals: [Int]) -> [Vertex] {
vals.map { Vertex(val: $0) }
}
/* vets vals */
public static func vetsToVals(vets: [Vertex]) -> [Int] {
vets.map { $0.val }
}
}