I have nothing important to do recently, so I have time to look at data structure and write about it, so as to activate my mental thinking.

In computer science, data structures are the ways in which data is stored and organized in a computer. Data structure and algorithm are more abstract, learning or need a certain amount of perseverance. Broadly speaking, data structure refers to the storage structure of a group of data, and algorithm is a group of methods to manipulate data. Algorithms and data structures complement each other. Data structures serve algorithms, which operate on specific data structures.

Introduction to LeetCode Data structures

217. There are duplicate elements

Some of the more unusual test cases:

  • [1, 2, 3, 1)
  • [1, 1, 1, 3, 3, 4, 3, 2, 4, 2]
  • [1, 2, 3, 4]
  • [0]
  • [7, 3, 2, 1, 2]
  • [1, 5, -2, -4, 0]
  • [2, 14, 18, 22, 22]

At present, individual thoughts can be divided into three different realization directions:

  • Direction one: Not using the convenience apis provided by arrays
    • In addition to the basic operations (push, POP, unshift, shift, slice, splice)
  • Direction two: You can use all the apis provided by arrays
  • Direction 3: Other skills

Note: The code that appears below can be overwritten using for


Direction of a

1. Double cycle method

1.1 the violence

function containsDuplicate(nums: number[]) :boolean {
    let i = 0
    let j = 0
    while (i < nums.length) { // n
        const item = nums[i]
        while (j < nums.length) { // n
            if (item === nums[j]) {return true}
            j++
        }
        i++
    }
    return false
};
Copy the code

Time complexity: O(n^2) Problem: Self vs. self will be true result: not applicable

1.2 optimization

function containsDuplicate(nums: number[]) :boolean {
    let i = 0
    let j = i + 1
    while (i < nums.length) { // n
        const item = nums[i]
        while (j < nums.length) { // n - 1
            if (item === nums[j]) { return true }
            j++
        }
        i++
        j = i + 1
    }
    return false
};
Copy the code

Time complexity: On(n * (n-1)) => O(n^2) Problem: Because it is sequential, it takes too long to compare duplicate elements at the end of the loop

2. Double pointer

2.1 Space Usage

function containsDuplicate(nums: number[]) :boolean {
    const arr = []

    const findNum = (num: number) :boolean= > {
        let kl = 0
        let kr = arr.length - 1
        while (kl <= kr) {
            if (num === arr[kl] || num === arr[kr]) { return true }
            kl++
            kr--
        }
        return false
    }

    let i = 0
    let j = nums.length - 1

    while (i <= j) { // n / 2 
        const l = nums[i]
        const r = nums[j]
        if (i === j && findNum(l)) { return true } // n / 2+1
        if (l === r) { return true }
        if (findNum(l)) { return true } // n / 2 + 1
        if (findNum(r)) { return true } // n / 2 + 1
        arr.push(l)
        arr.push(r)
        i++
        j--
    }
    return false
};
Copy the code

Time complexity: O(3m * n) => O(mn) Problem: Extra space is needed to record the traversed value, and it needs to be traversed again from the history. Boundary condition results in multiple cases need to be processed: Can be implemented, but the implementation is logically optimized and can be implemented without additional space

2.2 Optimization, no use of space

function containsDuplicate(nums: number[]) :boolean {
   let i = 0
   let j = nums.length - 1

   while (i <= j) { // n
       const l = nums[i]
       const r = nums[j]
       if(l === r && i ! == j)return true
       let ci = i + 1
       let cj = j - 1
       while (ci <= cj) { // n
           if (l === nums[ci] || l === nums[cj]) return true
           if (r === nums[ci] || r === nums[cj]) return true
           ci++
           cj--
       }
       i++
       j--
   }
   return false
};
Copy the code

The boundary condition greatly reduces the time complexity: O(n * n) => O(n^2) Problem: Although no extra space is occupied and the inner loop also uses double Pointers, it does not change its complexity. Result: It can be implemented without changing its complexity


Direction of the second

1. The use of indexOf

function containsDuplicate(nums: number[]) :boolean {
    for (let i = 0; i < nums.length; i++) { // n
        if (nums.indexOf(nums[i], i + 1)! = = -1) return true // n
    }
    return false
};
Copy the code

Time complexity: O(n * n) => O(n^2) Problem: Using the indexOf API implementation, it looks like O(1) but is still O(n) internal result: achievable

2. The use of the sort

function containsDuplicate(nums: number[]) :boolean {
    if(! nums || ! nums.length)return false

    nums = nums.sort()
    for (let i = 0; i < nums.length; i++) {
        if (nums[i] === nums[i + 1]) return true
    }
    return false
};
Copy the code

Time complexity: O(n + n) => O(n) Problem: Elements of a single type are feasible. If complex types occur, more cases need to be considered. Result: Yes


Direction of # 3

1. Use the object key

function containsDuplicate(nums: number[]) :boolean {
  if(! nums || ! nums.length)return false

  const obj: { [key: string] :number } = {}
  for (let i = 0; i < nums.length; i++) {
    if (obj[nums[i]]) { return true }
    if(! obj[nums[i]]) { obj[nums[i]] =1}}return false
};
Copy the code

Features: Using the non-repeatable key of the object, if the existing key is encountered, it can be confirmed that there are duplicate elements: O(n) Problem: Using the type feature, but not the result of algorithm implementation: achievable

2. Use the Set new data type

function containsDuplicate(nums: number[]) :boolean {
  if(! nums || ! nums.length)return false

  const nNums = new Set(nums)
  return nums.length > nNums.size
};
Copy the code

Features: Using the Set natural de-weight feature, through the array length comparison can be directly concluded time complexity: O(1) problem: belongs to the use of type characteristics, not algorithm implementation results: can be achieved

3. Make use of Map new data types

function containsDuplicate(nums: number[]) :boolean {
  if(! nums || ! nums.length)return false

  const nNums = new Map(a)for (let i = 0; i < nums.length; i++) {
    if (nNums.has(nums[i])) { return true }
    else { nNums.set(nums[i], 1)}}return false
};
Copy the code

Time complexity: O(n) Problem: Using type feature, not algorithm implementation result: achievable