Skip to content

Commit ca2f02e

Browse files
committed
Added swift
1 parent 29f0ffc commit ca2f02e

File tree

82 files changed

+5237
-315
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+5237
-315
lines changed

README.md

Lines changed: 307 additions & 307 deletions
Large diffs are not rendered by default.

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

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,68 @@ There is a cycle in a linked list if there is some node in the list that can be
4444
* <code>-10<sup>5</sup> <= Node.val <= 10<sup>5</sup></code>
4545
* `pos` is `-1` or a **valid index** in the linked-list.
4646

47-
**Follow up:** Can you solve it using `O(1)` (i.e. constant) memory?
47+
**Follow up:** Can you solve it using `O(1)` (i.e. constant) memory?
48+
49+
To solve the problem, we can use Floyd's Tortoise and Hare algorithm, also known as the Floyd's Cycle Detection algorithm. This algorithm involves two pointers, one moving at twice the speed of the other. If there's a cycle in the linked list, these two pointers will eventually meet. Once they meet, we reset one pointer to the head of the list and move both pointers at the same speed. The point where they meet again will be the start of the cycle.
50+
51+
Here's how we can implement this algorithm in Python using a `Solution` class:
52+
53+
```python
54+
class ListNode:
55+
def __init__(self, val=0, next=None):
56+
self.val = val
57+
self.next = next
58+
59+
class Solution:
60+
def detectCycle(self, head: ListNode) -> ListNode:
61+
# Function to detect cycle and return the node where cycle starts
62+
63+
# Step 1: Initialize slow and fast pointers
64+
slow = fast = head
65+
66+
# Step 2: Find the meeting point of the two pointers
67+
while fast and fast.next:
68+
slow = slow.next
69+
fast = fast.next.next
70+
if slow == fast:
71+
break
72+
73+
# If there's no cycle, return None
74+
if not fast or not fast.next:
75+
return None
76+
77+
# Step 3: Reset one pointer to the head and move both pointers at the same speed
78+
slow = head
79+
while slow != fast:
80+
slow = slow.next
81+
fast = fast.next
82+
83+
# Step 4: Return the node where the two pointers meet again (start of cycle)
84+
return slow
85+
86+
# Example usage:
87+
# Create linked list nodes
88+
node1 = ListNode(3)
89+
node2 = ListNode(2)
90+
node3 = ListNode(0)
91+
node4 = ListNode(-4)
92+
93+
# Connect nodes to form a cycle
94+
node1.next = node2
95+
node2.next = node3
96+
node3.next = node4
97+
node4.next = node2 # This creates a cycle
98+
99+
# Create an instance of Solution class
100+
solution = Solution()
101+
102+
# Call detectCycle method to find the start of the cycle
103+
cycle_start = solution.detectCycle(node1)
104+
105+
if cycle_start:
106+
print("Tail connects to node index:", cycle_start.val)
107+
else:
108+
print("No cycle")
109+
```
110+
111+
This solution has a time complexity of O(n) and uses O(1) extra space.

src/main/python/g0101_0200/s0146_lru_cache/readme.md

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,105 @@ The functions `get` and `put` must each run in `O(1)` average time complexity.
3737
* <code>0 <= key <= 10<sup>4</sup></code>
3838
* <code>0 <= value <= 10<sup>5</sup></code>
3939
* At most 2<code> * 10<sup>5</sup></code> calls will be made to `get` and `put`.
40+
41+
To solve the problem and implement the LRU Cache, we can use a combination of a dictionary (hash map) and a doubly linked list. This approach allows us to achieve O(1) time complexity for both the `get` and `put` operations.
42+
43+
### Steps:
44+
45+
1. **Define a Doubly Linked List Node**:
46+
- Define a class for the doubly linked list node with attributes `key`, `value`, `prev`, and `next`.
47+
48+
2. **Initialize the LRU Cache**:
49+
- Initialize the LRU cache with a dictionary to store key-value pairs and two dummy nodes for the head and tail of the doubly linked list.
50+
- Set `capacity` to the provided capacity.
51+
- Initialize a `size` variable to keep track of the number of elements in the cache.
52+
53+
3. **Implement `get` Operation**:
54+
- If the key exists in the cache, move the corresponding node to the front of the doubly linked list (indicating it was recently used) and return its value.
55+
- If the key does not exist, return -1.
56+
57+
4. **Implement `put` Operation**:
58+
- If the key exists in the cache, update its value and move the corresponding node to the front of the doubly linked list.
59+
- If the key does not exist:
60+
- If the cache is full (`size` equals `capacity`), remove the least recently used node (tail node) from the doubly linked list and the dictionary.
61+
- Create a new node with the provided key and value, add it to the front of the doubly linked list, and insert the key-value pair into the dictionary.
62+
- Update the `size` accordingly.
63+
64+
### Implementation:
65+
66+
```python
67+
class LRUCache:
68+
class ListNode:
69+
def __init__(self, key=0, value=0):
70+
self.key = key
71+
self.value = value
72+
self.prev = None
73+
self.next = None
74+
75+
def __init__(self, capacity: int):
76+
self.capacity = capacity
77+
self.cache = {}
78+
self.head = self.ListNode()
79+
self.tail = self.ListNode()
80+
self.head.next = self.tail
81+
self.tail.prev = self.head
82+
self.size = 0
83+
84+
def _add_node(self, node):
85+
node.prev = self.head
86+
node.next = self.head.next
87+
self.head.next.prev = node
88+
self.head.next = node
89+
90+
def _remove_node(self, node):
91+
prev_node = node.prev
92+
next_node = node.next
93+
prev_node.next = next_node
94+
next_node.prev = prev_node
95+
96+
def _move_to_front(self, node):
97+
self._remove_node(node)
98+
self._add_node(node)
99+
100+
def get(self, key: int) -> int:
101+
if key in self.cache:
102+
node = self.cache[key]
103+
self._move_to_front(node)
104+
return node.value
105+
else:
106+
return -1
107+
108+
def put(self, key: int, value: int) -> None:
109+
if key in self.cache:
110+
node = self.cache[key]
111+
node.value = value
112+
self._move_to_front(node)
113+
else:
114+
if self.size == self.capacity:
115+
del self.cache[self.tail.prev.key]
116+
self._remove_node(self.tail.prev)
117+
self.size -= 1
118+
new_node = self.ListNode(key, value)
119+
self._add_node(new_node)
120+
self.cache[key] = new_node
121+
self.size += 1
122+
```
123+
124+
### Explanation:
125+
126+
1. **Define a Doubly Linked List Node**:
127+
- We define a nested class `ListNode` to represent nodes in the doubly linked list. Each node contains `key`, `value`, `prev`, and `next` attributes.
128+
129+
2. **Initialize the LRU Cache**:
130+
- In the `__init__` method, we initialize the LRU cache with the provided `capacity`, an empty dictionary `cache` to store key-value pairs, and two dummy nodes `head` and `tail` for the head and tail of the doubly linked list. We set `head.next` to `tail` and `tail.prev` to `head` to link them together. We also initialize `size` to 0.
131+
132+
3. **Implement `get` Operation**:
133+
- In the `get` method, if the key exists in the cache, we move the corresponding node to the front of the doubly linked list using the `_move_to_front` method and return its value. If the key does not exist, we return -1.
134+
135+
4. **Implement `put` Operation**:
136+
- In the `put` method, if the key exists in the cache, we update its value and move the corresponding node to the front of the doubly linked list. If the key does not exist:
137+
- If the cache is full, we remove the least recently used node (tail node) from the doubly linked list and the dictionary.
138+
- We create a new node with the provided key and value, add it to the front of the doubly linked list, and insert the key-value pair into the dictionary.
139+
- We update the `size` accordingly.
140+
141+
This implementation ensures that both `get` and `put` operations run in O(1) average time complexity.

src/main/python/g0101_0200/s0148_sort_list/readme.md

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,97 @@ Given the `head` of a linked list, return _the list after sorting it in **ascend
3131
* The number of nodes in the list is in the range <code>[0, 5 * 10<sup>4</sup>]</code>.
3232
* <code>-10<sup>5</sup> <= Node.val <= 10<sup>5</sup></code>
3333

34-
**Follow up:** Can you sort the linked list in `O(n logn)` time and `O(1)` memory (i.e. constant space)?
34+
**Follow up:** Can you sort the linked list in `O(n logn)` time and `O(1)` memory (i.e. constant space)?
35+
36+
To solve the problem of sorting a linked list, you can use the merge sort algorithm, which is suitable for linked lists because it provides an O(n log n) time complexity. This approach can be implemented recursively and achieves the required efficiency.
37+
38+
Here are the detailed steps and the corresponding implementation using the `Solution` class:
39+
40+
### Steps:
41+
42+
1. **Base Case**:
43+
- If the linked list is empty or has only one node, it is already sorted. Return the head.
44+
45+
2. **Split the List**:
46+
- Use the fast and slow pointer technique to find the middle of the linked list. This will help to split the linked list into two halves.
47+
- `slow` moves one step at a time, while `fast` moves two steps at a time.
48+
- When `fast` reaches the end, `slow` will be at the middle point of the list.
49+
50+
3. **Sort Each Half**:
51+
- Recursively sort the left half and the right half of the list.
52+
53+
4. **Merge the Sorted Halves**:
54+
- Merge the two sorted halves into a single sorted list.
55+
56+
### Implementation:
57+
58+
```python
59+
class ListNode:
60+
def __init__(self, val=0, next=None):
61+
self.val = val
62+
self.next = next
63+
64+
class Solution:
65+
def sortList(self, head: ListNode) -> ListNode:
66+
if not head or not head.next:
67+
return head
68+
69+
# Step 2: Split the list into two halves
70+
mid = self.getMid(head)
71+
left = head
72+
right = mid.next
73+
mid.next = None
74+
75+
# Step 3: Sort each half
76+
left = self.sortList(left)
77+
right = self.sortList(right)
78+
79+
# Step 4: Merge the sorted halves
80+
return self.merge(left, right)
81+
82+
def getMid(self, head: ListNode) -> ListNode:
83+
slow = head
84+
fast = head
85+
while fast.next and fast.next.next:
86+
slow = slow.next
87+
fast = fast.next.next
88+
return slow
89+
90+
def merge(self, list1: ListNode, list2: ListNode) -> ListNode:
91+
dummy = ListNode()
92+
tail = dummy
93+
94+
while list1 and list2:
95+
if list1.val < list2.val:
96+
tail.next = list1
97+
list1 = list1.next
98+
else:
99+
tail.next = list2
100+
list2 = list2.next
101+
tail = tail.next
102+
103+
if list1:
104+
tail.next = list1
105+
if list2:
106+
tail.next = list2
107+
108+
return dummy.next
109+
```
110+
111+
### Explanation:
112+
113+
1. **Base Case**:
114+
- The function `sortList` checks if the list is empty or has a single node, in which case it returns the head as it is already sorted.
115+
116+
2. **Split the List**:
117+
- The `getMid` function finds the middle of the list using the fast and slow pointer technique.
118+
- The list is then split into two halves: `left` starting from the head to the middle, and `right` starting from the node after the middle.
119+
120+
3. **Sort Each Half**:
121+
- The `sortList` function is called recursively on both halves to sort them.
122+
123+
4. **Merge the Sorted Halves**:
124+
- The `merge` function merges the two sorted halves into a single sorted linked list.
125+
- A dummy node is used to simplify the merging process, and a `tail` pointer is used to build the new sorted list.
126+
127+
This approach ensures that the linked list is sorted in O(n log n) time complexity, which is optimal for this problem. The space complexity is O(log n) due to the recursion stack.

src/main/python/g0101_0200/s0152_maximum_product_subarray/readme.md

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,69 @@ A **subarray** is a contiguous subsequence of the array.
2828

2929
* <code>1 <= nums.length <= 2 * 10<sup>4</sup></code>
3030
* `-10 <= nums[i] <= 10`
31-
* The product of any prefix or suffix of `nums` is **guaranteed** to fit in a **32-bit** integer.
31+
* The product of any prefix or suffix of `nums` is **guaranteed** to fit in a **32-bit** integer.
32+
33+
To solve the problem of finding the maximum product subarray, you can use a dynamic programming approach to keep track of the maximum and minimum products at each position in the array. This approach works because the product of two negative numbers can be positive, and thus the minimum product can become the maximum if a negative number is encountered.
34+
35+
Here are the detailed steps and the corresponding implementation in the `Solution` class:
36+
37+
### Steps:
38+
39+
1. **Initialization**:
40+
- Check if the input array `nums` is empty. If it is, return 0.
41+
- Initialize three variables:
42+
- `max_product` to keep track of the maximum product found so far.
43+
- `current_max` to keep track of the maximum product ending at the current position.
44+
- `current_min` to keep track of the minimum product ending at the current position.
45+
46+
2. **Iterate through the Array**:
47+
- Loop through each element in the array starting from the first element.
48+
- For each element, calculate the potential new values for `current_max` and `current_min` considering the current element itself, the product of `current_max` with the current element, and the product of `current_min` with the current element.
49+
- Update `current_max` to be the maximum of these values.
50+
- Update `current_min` to be the minimum of these values.
51+
- Update `max_product` to be the maximum of `max_product` and `current_max`.
52+
53+
3. **Return Result**:
54+
- After the loop, `max_product` will hold the maximum product of any subarray within `nums`.
55+
56+
### Implementation:
57+
58+
```python
59+
class Solution:
60+
def maxProduct(self, nums: List[int]) -> int:
61+
if not nums:
62+
return 0
63+
64+
max_product = nums[0]
65+
current_max = nums[0]
66+
current_min = nums[0]
67+
68+
for num in nums[1:]:
69+
if num < 0:
70+
current_max, current_min = current_min, current_max
71+
72+
current_max = max(num, current_max * num)
73+
current_min = min(num, current_min * num)
74+
75+
max_product = max(max_product, current_max)
76+
77+
return max_product
78+
```
79+
80+
### Explanation:
81+
82+
1. **Initialization**:
83+
- `max_product` is initialized to the first element of the array because the maximum product subarray must include at least one element.
84+
- `current_max` and `current_min` are also initialized to the first element.
85+
86+
2. **Iterate through the Array**:
87+
- For each element in `nums` (starting from the second element):
88+
- If the current element is negative, swap `current_max` and `current_min` because multiplying by a negative number flips the maximum and minimum.
89+
- Update `current_max` to be the maximum of the current element or the product of `current_max` with the current element.
90+
- Update `current_min` to be the minimum of the current element or the product of `current_min` with the current element.
91+
- Update `max_product` to be the maximum of `max_product` and `current_max`.
92+
93+
3. **Return Result**:
94+
- The `max_product` variable now contains the maximum product of any contiguous subarray.
95+
96+
This solution efficiently finds the maximum product subarray in O(n) time complexity with O(1) additional space complexity.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy