算法训练营day6(补),哈希表2

昨天三数之和未做出来,今天补发

四数相加 II

func fourSumCount(nums1 []int, nums2 []int, nums3 []int, nums4 []int) int {

  map1 := make(map[int]int)

  count := 0

  // 遍历大nums1和大nums1数组,统计两个数组元素之和,和出现的次数,放到map中

  for _, v := range nums1 {

    for _, v1 := range nums2 {

      map1[v+v1]++

    }

  }

  // 在遍历大nums3和大nums4数组,找到如果 0-(v+v1) 在map中出现过的话,就把map中key对应的value也就是出现次数统计出来。

  for _, v := range nums3 {

    for _, v1 := range nums4 {

      target := 0 - (v + v1)

      _, ok := map1[target]

      if ok {

        count = count + map1[target]

      }

    }

  }

  return count

}

383. 赎金信

//原理和有效字母异位词相似

func canConstruct(ransomNote string, magazine string) bool {

  nums := make([]int, 26)

  r := ransomNote

  m := magazine

  if len(r) > len(m) {

    return false

  }

  for i := 0; i < len(m); i++ {

    // 通过nums数据记录 magazine里各个字符出现次数

    index := int(m[i])

    nums[index-97]++

  }

  for j := 0; j < len(r); j++ {

    // 遍历ransomNote,在nums里对应的字符个数做--操作

    index := int(r[j])

    nums[index-97]--

   // 如果小于零说明ransomNote里出现的字符,magazine没有

    if nums[index-97] < 0 {

      return false

    }

  }

  return true

}

15. 三数之和

func threeSum(nums []int) [][]int {

  size := len(nums)

  if size < 3 {

    return nil

  }

  //先对数组进行排序

  sort.Ints(nums)

  result := [][]int{}

  for i := 0; i < size-2; i++ {

    n1 := nums[i]

    //剪枝处理, 因为n1>0加上任何数都比0大直接跳过

    if n1 > 0 {

      break

    }

    //去除重复元素

    if i > 0 && n1 == nums[i-1] {

      continue

    }

    left := i + 1

    right := size - 1

    // 因为元素不能重叠,所以left < right

    for left < right {

      n2 := nums[left]

      n3 := nums[right]

      res := n1 + n2 + n3

      // res==0找到对应元素放到二维数组里

      if res == 0 {

        result = append(result, []int{n1, n2, n3})

        //再度去重,注意是for千万别写成if,否则会有遗漏

        for left < right && n2 == nums[left] {

          left++

        }

        for left < right && n3 == nums[right] {

          right--

        }

        //找不到左右收缩指针

      } else if res > 0 {

        right--

      } else {

        left++

      }

    }

  }

  return result

}

18. 四数之和

func fourSum(nums []int, target int) [][]int {

  size := len(nums)

  if size < 4 {

    return nil

  }

  //先对数组进行排序

  sort.Ints(nums)

  result := [][]int{}

  for i := 0; i < size-3; i++ {

    n1 := nums[i]

    //第一层剪枝处理,因为target是变量去考虑target<0的情况

    if n1 > target && n1 >= 0 {

      break

    }

    //去除重复元素

    if i > 0 && n1 == nums[i-1] {

      continue

    }

    //降维处理,把4数之和降位3数和,就可以按照3数之和逻辑处理

    for j := i + 1; j < size; j++ {

      n2 := nums[j]

      //第二层剪枝处理,因为target是变量去考虑target<0的情况

      if n2+n1 > target && n2+n1 >= 0 {

        break

      }

      //去除重复元素

      if j > i+1 && n2 == nums[j-1] {

        continue

      }

      left := j + 1

      right := size - 1

      // 因为元素不能重叠,所以left < right

      for left < right {

        n3 := nums[left]

        n4 := nums[right]

        res := n1 + n2 + n3 + n4

        // res==0找到对应元素放到二维数组里

        if res == target {

          result = append(result, []int{n1, n2, n3, n4})

          //再度去重,注意是for千万别写成if,否则会有遗漏

          for left < right && n3 == nums[left] {

            left++

          }

          for left < right && n4 == nums[right] {

            right--

          }

          //找不到左右收缩指针

        } else if res > target {

          right--

        } else {

          left++

        }

      }

    }

  }

  return result

}