Skip to content

Commit 59595bf

Browse files
committed
Added tasks 153-208
1 parent f89775d commit 59595bf

File tree

16 files changed

+1293
-152
lines changed

16 files changed

+1293
-152
lines changed

README.md

+37
Large diffs are not rendered by default.

src/main/swift/g0101_0200/s0139_word_break/readme.md

+59-9
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,45 @@ Given a string `s` and a dictionary of strings `wordDict`, return `true` if `s`
3939
* `s` and `wordDict[i]` consist of only lowercase English letters.
4040
* All the strings of `wordDict` are **unique**.
4141

42-
## Solution
42+
To solve the "Word Break" problem:
43+
44+
The problem requires us to determine if a string `s` can be segmented into a sequence of words from a dictionary `wordDict`.
45+
46+
### Steps to Approach:
47+
48+
1. **Understanding the Problem:**
49+
- We need to check if we can partition the string `s` such that each partition is a word from `wordDict`.
50+
- The same word from `wordDict` can be reused multiple times.
51+
52+
2. **Recursive Approach with Memoization:**
53+
- We'll use a recursive function (`canBeBroken`) that will attempt to break down the string `s` starting from each index.
54+
- Memoization (using `visited` array) helps avoid redundant computations by remembering if a substring starting from a particular index has already been processed.
55+
56+
3. **Implementation Details:**
57+
58+
- **Initialization:** Convert each word in `wordDict` into an array of characters (`words`). Initialize `sSlice` as an array of characters from `s`.
59+
- **Recursive Function (`canBeBroken`):**
60+
- **Base Case:** If `startIndex` equals `chars.endIndex`, return `true`, indicating that the entire string has been successfully segmented.
61+
- Check if `visited[startIndex]` is `true` to skip processing if the substring starting from `startIndex` has already been explored.
62+
- Iterate through each word in `words`:
63+
- Check if the current substring (`chars`) starts with the current `word`.
64+
- If it does, recursively call `canBeBroken` with the remaining substring (`chars[startIndex.advanced(by: word.count)...]`).
65+
- If the recursive call returns `true`, return `true` immediately.
66+
- If no valid segmentation is found with any word, mark `visited[startIndex]` as `true` and return `false`.
67+
- **Edge Cases:** Handle cases where `s` is empty or where no segmentation is possible with the given `wordDict`.
68+
69+
4. **Complexity:**
70+
- Time complexity is influenced by both the length of `s` and the number of words in `wordDict`.
71+
- Space complexity is primarily due to recursion depth and the `visited` array.
72+
73+
### Swift Implementation:
74+
75+
Here's the Swift implementation of the approach:
4376

4477
```swift
4578
class Solution {
4679
func wordBreak(_ s: String, _ wordDict: [String]) -> Bool {
47-
var words = [[Character]]()
80+
var words = \[\[Character]]()
4881
for word in wordDict {
4982
words.append(Array(word))
5083
}
@@ -61,17 +94,34 @@ class Solution {
6194
let startIndex = chars.startIndex
6295
guard startIndex != chars.endIndex else { return true }
6396
guard !visited[startIndex] else { return false }
97+
6498
for word in words {
65-
guard
66-
chars.starts(with: word),
67-
canBeBroken(chars[startIndex.advanced(by: word.count)...], words, &visited)
68-
else {
69-
continue
99+
guard chars.starts(with: word) else { continue }
100+
if canBeBroken(chars[startIndex.advanced(by: word.count)...], words, &visited) {
101+
return true
70102
}
71-
return true
72103
}
104+
73105
visited[startIndex] = true
74106
return false
75107
}
76108
}
77-
```
109+
```
110+
111+
### Explanation of the Swift Code:
112+
113+
- **Initialization (`wordBreak` function):**
114+
- Convert each word in `wordDict` into arrays of characters (`words`).
115+
- Convert the input string `s` into an array of characters (`sSlice`).
116+
- Initialize a `visited` array to keep track of whether a substring starting from each index has been explored.
117+
118+
- **Recursive Function (`canBeBroken`):**
119+
- **Base Case:** If `startIndex` equals `chars.endIndex`, return `true`, indicating successful segmentation.
120+
- Check if `visited[startIndex]` is `true` to avoid redundant computations.
121+
- Iterate through each word in `words`:
122+
- Check if the current substring (`chars`) starts with the current `word`.
123+
- If true, recursively call `canBeBroken` with the remaining substring (`chars[startIndex.advanced(by: word.count)...]`).
124+
- If the recursive call returns `true`, immediately return `true`.
125+
- If no valid segmentation is found, mark `visited[startIndex]` as `true` and return `false`.
126+
127+
This approach ensures that we explore all possible ways to segment `s` using words from `wordDict` while efficiently handling overlapping subproblems using memoization.

src/main/swift/g0101_0200/s0141_linked_list_cycle/readme.md

+64-25
Original file line numberDiff line numberDiff line change
@@ -49,35 +49,74 @@ Return `true` _if there is a cycle in the linked list_. Otherwise, return `false
4949

5050
**Follow up:** Can you solve it using `O(1)` (i.e. constant) memory?
5151

52-
## Solution
52+
To solve the "Linked List Cycle" problem, we can use the Floyd's Tortoise and Hare algorithm. This algorithm uses two pointers moving at different speeds to detect if a cycle exists in the linked list. Here’s a step-by-step guide and the Swift implementation of the solution.
5353

54-
```swift
55-
/**
56-
* Definition for singly-linked list.
57-
* public class ListNode {
58-
* public var val: Int
59-
* public var next: ListNode?
60-
* public init(_ val: Int) {
61-
* self.val = val
62-
* self.next = nil
63-
* }
64-
* }
65-
*/
66-
class Solution {
67-
func hasCycle(_ head: ListNode?) -> Bool {
54+
### Steps to Solve the Problem
55+
56+
1. **Initialization:**
57+
- Define two pointers, `slow` and `fast`, both starting at the head of the linked list.
58+
59+
2. **Traversal and Cycle Detection:**
60+
- Move the `slow` pointer one step at a time.
61+
- Move the `fast` pointer two steps at a time.
62+
- If there is a cycle, the `fast` pointer will eventually meet the `slow` pointer.
63+
- If the `fast` pointer reaches the end of the list (i.e., `fast` or `fast.next` becomes `nil`), there is no cycle in the linked list.
6864

69-
var slow = head
70-
var fast = head
65+
3. **Return Result:**
66+
- If the `fast` pointer meets the `slow` pointer, return `true` indicating a cycle.
67+
- If the `fast` pointer reaches the end, return `false`.
7168

72-
while fast != nil && fast?.next != nil {
73-
slow = slow?.next
74-
fast = fast?.next?.next
69+
### Swift Implementation
7570

76-
if slow === fast {
77-
return true
71+
Here’s the implementation of the `Solution` class using the Floyd's Tortoise and Hare algorithm:
72+
73+
```swift
74+
// Definition for singly-linked list.
75+
class ListNode {
76+
var val: Int
77+
var next: ListNode?
78+
init(_ val: Int) {
79+
self.val = val
80+
self.next = nil
81+
}
82+
}
83+
84+
class Solution {
85+
func hasCycle(_ head: ListNode?) -> Bool {
86+
// Initialize slow and fast pointers
87+
var slow = head
88+
var fast = head
89+
90+
// Traverse the linked list
91+
while fast != nil && fast?.next != nil {
92+
slow = slow?.next // Move slow pointer one step
93+
fast = fast?.next?.next // Move fast pointer two steps
94+
95+
// Check if slow and fast pointers meet
96+
if slow === fast {
97+
return true
98+
}
7899
}
79-
}
80-
return false
100+
101+
// If we reach here, there is no cycle
102+
return false
81103
}
82104
}
83-
```
105+
```
106+
107+
### Explanation of the Swift Code
108+
109+
1. **Initialization:**
110+
- The `ListNode` class defines the structure of a node in the linked list.
111+
- The `Solution` class contains the `hasCycle` method which checks for a cycle.
112+
113+
2. **Traversal and Cycle Detection:**
114+
- The `while` loop continues as long as `fast` and `fast?.next` are not `nil`.
115+
- The `slow` pointer is moved one step (`slow = slow?.next`).
116+
- The `fast` pointer is moved two steps (`fast = fast?.next?.next`).
117+
118+
3. **Cycle Detection:**
119+
- If the `slow` pointer and `fast` pointer meet (`if slow === fast`), it indicates there is a cycle, and the method returns `true`.
120+
- If the loop exits because `fast` or `fast?.next` is `nil`, it means there is no cycle, and the method returns `false`.
121+
122+
This approach ensures that we use constant space (`O(1)`) while efficiently detecting the presence of a cycle in the linked list.

src/main/swift/g0101_0200/s0142_linked_list_cycle_ii/readme.md

+70-32
Original file line numberDiff line numberDiff line change
@@ -49,48 +49,86 @@ There is a cycle in a linked list if there is some node in the list that can be
4949

5050
**Follow up:** Can you solve it using `O(1)` (i.e. constant) memory?
5151

52-
## Solution
52+
To solve the "Linked List Cycle II" problem, we need to find the node where the cycle begins in a linked list, if there is a cycle. We'll use Floyd's Tortoise and Hare algorithm to detect the cycle and then determine the starting node of the cycle.
53+
54+
### Steps to Solve the Problem
55+
56+
1. **Cycle Detection:**
57+
- Use two pointers, `slow` and `fast`, to detect if a cycle exists. Both pointers start at the head of the linked list.
58+
- Move `slow` one step at a time and `fast` two steps at a time.
59+
- If `slow` and `fast` meet, a cycle exists.
60+
61+
2. **Finding the Start of the Cycle:**
62+
- If a cycle is detected, initialize another pointer, `start`, at the head of the list.
63+
- Move both `start` and `slow` one step at a time.
64+
- The point where they meet is the start of the cycle.
65+
66+
3. **Return Result:**
67+
- If no cycle is detected, return `nil`.
68+
- If a cycle is detected, return the node where `start` and `slow` meet.
69+
70+
### Swift Implementation
71+
72+
Here’s the Swift implementation of the `Solution` class:
5373

5474
```swift
55-
/**
56-
* Definition for singly-linked list.
57-
* public class ListNode {
58-
* public var val: Int
59-
* public var next: ListNode?
60-
* public init(_ val: Int) {
61-
* self.val = val
62-
* self.next = nil
63-
* }
64-
* }
65-
*/
75+
// Definition for singly-linked list.
76+
class ListNode {
77+
var val: Int
78+
var next: ListNode?
79+
init(_ val: Int) {
80+
self.val = val
81+
self.next = nil
82+
}
83+
}
84+
6685
class Solution {
6786
func detectCycle(_ head: ListNode?) -> ListNode? {
68-
if head == nil || head?.next == nil {
69-
return nil
70-
}
71-
87+
guard head != nil else { return nil }
88+
7289
var slow = head
7390
var fast = head
74-
91+
92+
// Cycle detection
7593
while fast != nil && fast?.next != nil {
76-
fast = fast?.next?.next
7794
slow = slow?.next
78-
95+
fast = fast?.next?.next
96+
7997
if slow === fast {
80-
break
98+
// Cycle detected, now find the start of the cycle
99+
var start = head
100+
while start !== slow {
101+
start = start?.next
102+
slow = slow?.next
103+
}
104+
return start
81105
}
82106
}
83-
84-
if fast == nil || fast?.next == nil {
85-
return nil
86-
}
87-
88-
slow = head
89-
while slow !== fast {
90-
slow = slow?.next
91-
fast = fast?.next
92-
}
93-
return slow
107+
108+
// No cycle detected
109+
return nil
94110
}
95111
}
96-
```
112+
```
113+
114+
### Explanation of the Swift Code
115+
116+
1. **Initialization:**
117+
- The `ListNode` class defines the structure of a node in the linked list.
118+
- The `Solution` class contains the `detectCycle` method which finds the start of the cycle if it exists.
119+
120+
2. **Cycle Detection:**
121+
- Initialize `slow` and `fast` pointers to the head of the linked list.
122+
- Use a `while` loop to move `slow` one step and `fast` two steps at a time.
123+
- If `slow` and `fast` meet, a cycle is detected.
124+
125+
3. **Finding the Start of the Cycle:**
126+
- If a cycle is detected, initialize `start` at the head of the list.
127+
- Move both `start` and `slow` one step at a time until they meet.
128+
- The meeting point is the start of the cycle.
129+
130+
4. **Return Result:**
131+
- If no cycle is detected, the function returns `nil`.
132+
- If a cycle is detected, the function returns the node where `start` and `slow` meet.
133+
134+
This approach ensures that we detect the cycle efficiently and find the starting node of the cycle using constant space (`O(1)` memory), adhering to the problem constraints.

0 commit comments

Comments
 (0)