算法题目(python实现)

来源经典算法解题实战

整型数组二

Product of Array Exclude Itself

Given an integers array A.

Define B[i] = A[0] * ... * A[i-1] * A[i+1] * ... * A[n-1], calculate B WITHOUT divide operation.

Example
For A=[1, 2, 3], return [6, 3, 2].

一般的想法

def solution(arr):
    length = len(arr)
    result = []
    for i in range(length):
        for j in range(length):
            m = 1
            if i != j:
                m *= arr[j]
        result.append(m)
    return result

每个元素都需要重新累乘得到, 可以将累乘的结果保存到左右数组中

def solution(arr):
  length = len(arr)
  result = []
  left_arr = [1 for i in range(length)]
  right_arr = [1 for i in range(length)]
  for i in range(length):
    if i > 0:
      left_arr[i] = left_arr[i -1] * arr[i - 1]
      right_arr[length - i - 1] = right_arr[ length - i] * arr[length - i]
  for i in range(length):
    result.append(left_arr[i] * right_arr[i])
  # result = [left_arr[i]* rigjt_arr[i] for i in range(length)]
  return result

同时可以将结果代替其中一个数组, 以减少内存的使用

def solution(arr):
  length = len(arr)
  # 数组长度小于2时, 直接返回[]
  if length < 2:
    return []
  result = [1 for i in range(length)]
  for i in range(1, length):
    result[i] = result[i - 1] * arr[i - 1]
  m = 1
  for i in range(length-2, -1, -1):
    m *= arr[i + 1]
    result[i] = m * result[i]
  return result

索引变换的时候有点懵, 不知道为什么. ?

Partition Array

Given an array nums of integers and an int k, partition the array (i.e move the elements in "nums") such that:
All elements < k are moved to the left
All elements >= k are moved to the right
Return the partitioning index, i.e the first index i nums[i] >= k.

If nums = [3,2,2,1] and k=2, a valid answer is 1.
数列中小于某值放在左边, 剩下的自然在右边.

  • 注意的是在某结果判断后, 再对其操作, 原先的判断失效(犯的错误)
def solution(arr, k):
    right = 0
    length = len(arr)
    for i in range(length):
        # 注意第二个条件, 避免对调换后的数组再进行判断
        while arr[i] >= k and length -right -1 < i:
            right += 1
            temp = arr[i]
            arr[i] = arr[length - right]
            arr[length - right] = temp
    return length - right

或者是下面这个方法更清晰

def solution(arr, k):
    length = len(arr)
    right = length -1
    left = 0
    i = 0
    while left <= right:
        print(arr[i], arr[left], arr[right])
        if arr[i] < k:
              arr[i], arr[left] = arr[left], arr[i]
              left += 1
        else:
              # arr[i], arr[right] = arr[right], arr[i]加上这句就错了, 因为如果这样调换, 会将未知的元素换到i位上, i++,从而没有判断.将需要的换到左边, 剩下的自然在右边
              right -= 1
        i += 1
  return left

First Missing Positive

Given an unsorted integer array, find the first missing positive integer.
Example
Given [1,2,0] return 3, and [3,4,-1,1] return 2.
Challenge
Your algorithm should run in O(n) time and uses constant space.

看题的时候没注意是正整数,可以得到第一个缺少的整数

  • 基本的方法和计数排序一样
  • 注意的是在自身上交换, 交换的判断条件是:1.索引(变换)和元素不相等 和 2.交换的两个元素值不等 ;3.注意因为交换到指定索引处, 首先还需判断索引是否越界
  • 将每一个元素交换到正确的位置.
    如果暂时没有满足的位置, 就不处理. 因为每一个元素都会交换到相应位置.如果该位置和元素不对应,则说明该位置没有相应的元素.
  • 还有就是在循环外使用target=arr[i] - min_n, 在循环中arr[i] 值已经变化, 又犯了这样的错误
def solution(arr):
  # 判断第一个正整数就不需要找最小值
  min_n = min(arr)
  length = len(arr)
  for i in range(length):
    target = arr[i] - min_n
    # 一直交换元素直至不满足条件
    while target <= length - 1 and target != i and arr[i] != arr[target]:
      arr[i], arr[target] = arr[target], arr[i]
      # 这里需要注意, 循环中arr[i]发生了变化
      target = arr[i] - min_n
  for i in range(length):
    if arr[i] -min_n != i:
      return i + min_n
  else:
    return min_n + length - 1

sum

标记: ??

Given an array of integers, find two numbers such that they can add up to a specific target number.
the function twoSum should return indices of two numbers such that they add up to the target, where index1 must be less than index2. Please note that your answer is not zero-based

numbers=[2, 7, 11, 15], target=9
return [1, 2]
you may assume that each input may would have exactly one

可以将目标值减去列表中每个数的结果作为字典的键, 在碰到下一个元素检查字典中是否含有该键.如果有则找到正确的两个数

def solution(arr, target):
  hashdict = {}
  for k, val in enumerate(arr):
    dict_k = target - val
    if dict_k in hashdict:
      return [hashdict[dict_k], k  + 1]
    else:
      hashdict[dict_k] = k + 1
return []

另一个是先排序, 再找

3 sum

Given an array s of n integers, are there elements a, b, c in s such that a+b+c=0?
find all unique triplets in the array which gives the sum of zero.
Example
For example, given array S = {-1 0 1 2 -1 -4}, A solution set is:
(-1, 0, 1)
(-1, -1, 2)
Note
Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
The solution set must not contain duplicate triplets.

将3 sum的问题转为2 sum问题. 用一个列表存储第一个0减第一个数字的结果, 然后求剩余的元素2 sum问题

def solution(arr):
    result = []
    temp = []
    # 列表排序, 使结果从小到大
    arr.sort()
    for i in arr:
        temp.append(0-i)
        # 将3  sum转换为 2 sum问题
    for i in range(len(arr)-2):
        if arr[i] in arr[:i]:
            continue
        hashdict = {}
        for k, value in enumerate(arr):
            if k <= i:
                continue
            target = temp[i] - value
            if value in hashdict:
                result.append((arr[i], arr[hashdict[value]], arr[k]))
            else:
                hashdict[target] = k
    return result

2sum 中不用字典, 排序后用j 和k 指向两个索引, 索引处元素相加如果大于目标值, 则k前移, 小于目标值, 则j后移, 知道j>=k

def solution(arr):
  # 无效的情况
  length = len(arr)
  if length < 3:
    return []
  result = []
  arr.sort()
  for i in range(length-2):
    if arr[i] in arr[:i]:
      continue
    # 2 sum
    j = i + 1
    k = length - 1
    while j < k:
      sum_three = arr[i] + arr[j] +arr[k]
      if sum_three ==0:
        result.append((arr[i], arr[j], arr[k]))
        # ...
        j += 1
      elif sum_three > 0:
        k -= 1
      else:
        j += 1
   return result

3 sum closest

Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target.
Return the sum of the three integers. You may assume that each input would have exactly one solution.
For example, given array S = {-1 2 1 -4}, and target = 1.
The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
两根指针i,j是o和length -1 , 他们的和 位于所有两个数之后的某个位置, 从大于(小于)某个状态单调减少(增加)到另一个状态

def solution(arr, target):
  result = 2**31 -1
  length = len(arr)
  if length < 3:
    return  result
  arr.sort()
  for i, item_i in enumerate(arr):
    # 留两个位置
    if i > length -3:
      break
    # 这是用来干什么的?判断最小的是否大于target值, 如果大于就不在循环下去
    if item_i + arr[i+1] + arr[i +2] > target:
      # 这里应该判断下result 和他的和大小
      result = min(result, item_i, arr[i + 1], arr[i + 2])
      break
    start = i  + 1
    end = length - 1
    # 接下来是在循环体之内用两根指针
    while start < end:
      #接下来是start += 1 or end -= 1
      # 先立个flag, 作为大于小于标记, 初始有两个状态
      flag = 0
      # 用一个temp变量保存他们的和
      temp = item_i + arr[start] + arr[end]
      result = min(abs(result - target), abs(temp - target))
      if temp > target:
          # flag变为-1, 假设是从小于状态变来的
          if flag == -1:
            break
          # 如果不是突变的, 则flag=1
          end -= 1
          flag = 1
      elif temp < target:
          if flag == 1:
            break
          flag = -1
          start += 1
      else:
        return temp
  return result
# 上面的错误
# 没有分清result 和 abs(temp-target)的关系
# 分支语句的冗余
def solution(arr, target):
    length = len(arr)
    if length < 3:
        return
    result =  2**31 -1
    arr.sort()
    for i in range(length - 2):
        temp = arr[i] + arr[i + 1] + arr[i + 2]
        if temp > target:
            result =  min(abs(temp - target), result)
            break
        start  =  i + 1
        end = length - 1
        flag = 0
        while start < end:
            temp = arr[i] + arr[start] + arr[end]
            if temp > target:
                if flag == -1:
                    break
                flag = 1
                end -= 1
            elif temp < target:
                if flag == 1:
                    break
                flag = -1
                start += 1
            else:
                return temp
            # 每次循环后都保存当前的结果, 以备最终使用
            last_temp = temp
        # 当跳出循环后, 说明从一个状态到另一个状态, 即last_temp到temp或者last_temp和temp相等, 这时求得结果
        result =  min(abs(temp - target), result, abs(last_temp - target))  
    return result

整型数组三

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容