【leetcode系列】一

LeetCode第一题

前言:昨天面试了字节跳动,最后跪在了算法题上,所以昨天开始暗下决心,每天刷一到两道算法题,而且特地开通了leetcode上字节跳动的公司题库会员,发现上面居然有800多道题,要刷完估计要点时间。所以决定工作日每天至少刷一道题,周末不上班的话刷两道,每道题都用php和python实现,希望自己能坚持下去,嘻嘻,也请大家监督。

题目:

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。

示例:

给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

这应该是leetcode上最简单的题目了,我相信大家都能解的出来,但是解出这个题不应该是我们刷题所追求的,我们刷题是为了能够锻炼自己的思维,所以当自己想出一套解题思路之后,看下自己的解法所需要的时间复杂度和空间复杂度,可以再想有木有其他解题思路,有木有更少的时间空间复杂度,当你可以提出跟别人不一样的思路,更少的时间空间复杂度,那你在众多竞争者就能脱颖而出,这是我们所追求的。

解题思路:

  1. 看完题目后的我,第一个想到的就是暴力解法了,两层嵌套循环,就能求出结果,但这样的解法的时间复杂度是O(n^2),空间复杂度是O(1),这种解法就不详细讲了。

  2. 那有木有更好的解法呢?肯定是有的,第一种解法的时间复杂度是O(n^2),空间复杂度只有O(1),那可不可以利用空间换时间的思想呢?在第一层遍历的时候把已经遍历的结果记录下来。因为是两数之和等于某个值,所以在遍历到某个值时,就可以通过 target-当前值 计算出在数组中存在的另一个值,然后等遍历到这个值时,判断之前是否存了这个值,如果有说明这两个数就是要求的结果,如果遍历完找不到,说明找不到。

  3. 第二种解法也是官方推荐的解法,时间复杂度是O(n),空间复杂度是O(n)。如果题目条件变化一下,给定的数组是排好序的,那一般这种情况就可以利用双指针法,一个低位,一个在高位,逐渐向中间逼近。如果和大于目标值,则高位向左移动一位,如果和小于目标值,则低位向右移动一位,直到找到和等于目标值,如果找不到说明不存在这样的两个值。这种条件下的解法时间复杂度是o(n)。有同学可能就会想,就算他给的不是有序的,那我不是可以先排序吗?如果你先排序,那可能数组对应的下标就发生改变了,但题目要求是要返回下标,所以这种解法行不通,但你如果有这种想法,说明你思维发散性挺高的,很好!

下面给出第二种,第三种解法(条件改动过的)的代码

php版

第二种解法:

//第二种解法,使用hash表记录,时间,空间复杂度都是O(n)
function two_sum_2($arr, $target)
{
  $n = count($arr);
  $map = [];

  for ($i = 0; $i < $n; $i++) {
    if (isset($map[$arr[$i]])) {
      return [$map[$arr[$i]], $i];
    }

    $map[$target-$arr[$i]] = $i;
  }

  return -1;
}

第三种解法:

改动条件一:给定的数组是已经排好序的,时间复杂度O(n),空间O(1)

//第三种解法,后用双指针法逼近,时间复杂度为O(n),空间复杂度为O(1)
function two_sum_3($arr, $target)
{
  $n = count($arr);
  $low = 0; $high = $n-1;

  while ($low < $high) {
    $sum = $arr[$low] + $arr[$high];
    if ($sum == $target) {
      return [$low, $high];
    } elseif ($sum > $target) {
      $high--;
    } else {
      $low++;
    }
  }

  return -1;
}

改动条件二:返回符合条件的两个数,而不是两个数的下标

//第三种解法,先排序,后用双指针法逼近,时间复杂度为O(nlogn),空间复杂度为O(1)
function two_sum_3($arr, $target)
{
  sort($arr);
  $n = count($arr);
  $low = 0; $high = $n-1;

  while ($low < $high) {
    $sum = $arr[$low] + $arr[$high];
    if ($sum == $target) {
      return [$arr[$low], $arr[$high]];
    } elseif ($sum > $target) {
      $high--;
    } else {
      $low++;
    }
  }

  return -1;
}

python版

第二种解法:

# 第二种解法,使用hash表记录,时间,空间复杂度都是O(n)
def two_sum_2(arr, target):
  hasmap = {}
  for i, item in enumerate(arr):
    if hasmap.get(item) is not None:
      return [i, hasmap.get(item)]
    hasmap[target-item] = i
  return -1

第三种解法:

改动条件一:给定的数组是已经排好序的,时间复杂度O(n),空间O(1)

# 第三种解法,双指针逼近
def two_sum_3(arr, target):
  n = len(arr)
  low = 0
  high = n - 1

  while low < high:
    sums = arr[low] + arr[high]
    if sums == target:
      return [low, high]
    elif sums > target:
      high = high - 1
    else:
      low = low + 1
  return -1

改动条件二:返回符合条件的两个数,而不是两个数的下标

# 第三种解法,双指针逼近
def two_sum_3(arr, target):
  arr = sorted(arr)
  n = len(arr)
  low = 0
  high = n - 1

  while low < high:
    sums = arr[low] + arr[high]
    if sums == target:
      return [arr[low], arr[high]]
    elif sums > target:
      high = high - 1
    else:
      low = low + 1
  return -1

本人正在学习python中,可能对python比较熟的小伙伴知道有更好的写法,也欢迎大家赐教,谢谢!

今天就先写这么多了,预定下期会推出 leetcode第二题,谢谢大家!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值