A: 26. Remove Duplicates from Sorted Array
Given a sorted array nums, remove the duplicates in-place such that each element appears only once and returns the new length. Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory. The relative order of elements should be kept the same. Return the number of unique elements in nums.
Clarification:
Confused why the returned value is an integer but your answer is an array?
Note that the input array is passed in by reference, which means a modification to the input array will be known to the caller as well.Example 1:
Input: nums = [1,1,2]
Output: 2, nums = [1,2]
Explanation: Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively. It doesn't matter what you leave beyond the returned length.
Example 2:Input: nums = [0,0,1,1,1,2,2,3,3,4]
Output: 5, nums = [0,1,2,3,4]
Explanation: Your function should return length = 5, with the first five elements of nums being modified to 0, 1, 2, 3, and 4 respectively. It doesn't matter what values are set beyond the returned length.
First version of the code:
function removeDuplicates(nums: number[]): number {
const record: Record<string, boolean> = {}
for (let i = 0; i < nums.length; i += 1) {
if (record[nums[i]]) {
nums.splice(i, 1)
i -= 1
} else {
record[nums[i]] = true
}
}
return nums.length
}
After submitting, the runtime and memory usage were only in the bottom 20% of the rankings. So I looked at the more optimal solutions in the solution section, which mentioned the "Two Pointers" approach.
The "Two Pointers" approach involves keeping track of two positions (not actual memory pointers) in the array: a fast pointer and a slow pointer. The fast pointer is used to iterate through the array, while the slow pointer keeps track of and modifies the position of the last unique element. When the fast pointer encounters a new different value, it is recorded at the position of slow+1. By the time the fast pointer has traversed the entire array, the slow pointer has recorded all the unique values. This method can be used because the array is sorted, which I initially overlooked in the problem statement.
Here is the code using the "Two Pointers" approach:
function removeDuplicates(nums: number[]): number {
if (nums.length < 2) {
return nums.length
}
let fast = 1
let slow = 0
while (fast < nums.length) {
if (nums[fast] !== nums[slow]) {
slow += 1
nums[slow] = nums[fast]
}
fast += 1
}
return slow + 1
}
When nums[fast] !== nums[slow]
, it means a new different value has been encountered. So this value is recorded at the position of slow+1
. By the time fast
has traversed the entire nums
, all the different values have been recorded by the slow pointer. This approach can also be used in similar scenarios, such as finding two numbers in a sorted array that sum up to a certain value. The overall idea is to keep track of two positions and perform iterations or operations on them, or both, such as moving from both ends towards the middle.
After seeing a lot of promotion for ChatGPT's Code Interpreter on YouTube, the author realized that there were still unmet needs in this area and decided to implement their own version.
Compared to the official version of ChatGPT, the advantages of this self-implemented version are: 1. It can access real-time data from the internet, such as generating a graph of Bitcoin's price curve in 2023; 2. It can be deployed locally, allowing it to interact with other local applications and have more flexible environment management, such as installing additional packages.
To implement the Code Interpreter, there are two key elements: first, utilizing the Function Calling capability of the OpenAI API to generate the code for the functions to be called; second, having an environment capable of executing Python code. For example, if a user specifies that they want to output a sine function graph, the code for drawing the sine function graph needs to be obtained and then executed in a Python interpreter to output the image for display to the user. During this process, the LLM Agent may also provide explanations and additional details about the results. Additionally, file I/O and the ability to save variables in the session need to be considered.
The Python interpreter, file I/O, and variable saving can all be seen as tools within LangChain, which can be integrated into LangChain and called when needed. The author has created a project called codebox-api to serve as this "Tool" (which was also shared during yesterday's check-in). Its underlying implementation creates a new Jupyter Kernel session whenever a new session is created.
The overall solution has been encapsulated into codeinterpreter-api by the author, making it easier for users to create sessions and execute the Code Interpreter.
The author's future plans include making it easier to deploy and expand, turning it into a production-ready API, and supporting more models such as Claude-V2 and Open Orca. The author also welcomes contributions from others.
A project that features over 2,000 classic DOS games in Chinese, which can be played on the web at dos.lol.
S: Reading notes on "The Hungry Age: The Gains and Losses of the Qianlong Era"
There is no unique standard for the system adopted by civilization. There is no best, only better. Qianlong has already maximized the efficiency of the feudal dynasty system, but it still cannot stop the wheels of history from rolling over the dynasty. To achieve the evolution of the system, the liberation of culture and thought is a necessary condition. Only with soaring and transcendent thoughts can civilization be pushed to the next stage (which could also be destruction).