随笔

Posted by Xuan Peng on July 1, 2019

刷题心得

  • python的list默认支持栈的方法pop()和append()(和push同一个功能)
  • “in-place”的题,想到指针
  • 物理层调制器作用:将数字信号转换成模拟信号
  • leetcode 53:maxSubArray
class Solution {
    public int maxSubArray(int[] nums) {
        int n = nums.length;
        int[] dp = new int[n];
        dp[0] = nums[0];
        int max = nums[0];
        for(int i=1; i<n; i++){
            if(dp[i-1] > 0)
                dp[i] = dp[i-1] + nums[i];
            else
                dp[i] = nums[i];
            max = Math.max(max, dp[i]);
        }
        return max;
    }
}
  • 这里写图片描述

  • A * "1+1+1+1+1+1+1+1 =?" *
      
    A : "上面等式的值是多少"
    B : *计算* "8!"
      
    A *在上面等式的左边写上 "1+" *
    A : "此时等式的值为多少"
    B : *quickly* "9!"
    A : "你怎么这么快就知道答案了"
    A : "只要在8的基础上加1就行了"
    A : "所以你不用重新计算因为你记住了第一个等式的值为8!动态规划算法也可以说是 '记住求过
       的解来节省时间'"
    
  • 动态规划算法的核心:记住已经解决过的子问题的解。

并查集

  • 用于解决动态连通性问题的逻辑数据结构

  • 包含两种操作:union()和connect()

  • union(x,y)给x,y之间添加一条connection

  • find(x,y)返回x和y之间是否连通,True/False

  • quickFind:

    1564886384223

  • quickUnion:

    • 想一想为什么每一次union都用是连通分量的根指向联通分量的根,这个步骤是提升效率的关键
    • 1564887048334
    • 1564887375654
  • quick-union和quick-find都不行

  • 改进:

    1. 每个连通分量引入权重(每个分量上的节点数),以此避免树线性化

    2. 每一个union操作,都将权重小的连通分量连在另一颗树上

      1564887609295

      • 复杂度分析:

        1564888317382

      • 再改进一下??:引入路径压缩

        • 1564888496570
          • 加入一行代码,每次让节点指向他的祖父节点,基本就能将整棵树展平
  • 最近生活过的不太规律,该学习的时候一定得找一个没地方躺的地方不然一趟就是大半天..
  • 之后的计划:两周内把leetcode100题刷完,Princeton算法课跟上,最后,小程序要急工赶完。

  • Python的五个标准数据类型:

    1. Numbers:包含int,long,float,short. int溢出会自动转化为long
    2. String:*是重复操作,+号是连接操作
    3. List:list[1:5:2] 返回list[1],list[3]和list[5]。第三个参数指定步长
    4. Tuple:只读列表,用tuple = ()创建
    5. Dict
    6. 在 python 中,strings, tuples, 和 numbers 是不可更改的对象,而 list,dict 等则是可以修改的对象。
    7. python 中一切都是对象,严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象。
  • 运算符:

    1. $$取幂运算:24 = 16
    2. //除法向下取整:7//3 = 2
  • id()函数获取对象内存地址,类似java hashcode()

  • is 与 == 区别:

    is 用于判断两个变量引用对象是否为同一个(同一块内存空间), == 用于判断引用变量的值是否相等。

    ==用于判断值,is 判断内存地址

    a=[1,2] b= a a==b(True) a is b(True)

    a= [1,2] b= a[:] a==b(True) a is b(False)

  • python list转string: string = ‘‘.join(list)

  • python sorted函数,返回所有可迭代对象的有序list形式

  • leetcode 55 Jump Game: Greedy and Dynamic Programming
  • leetcode 56 Merge Intervals:没吃透,复杂度太高(主要是memory copy操作太伤了),明天再来
  • OpenStack还是作为备选把,明天还是继续跟一下普林的算法课

8.09

  • Leetcode 64. Minimum Path Sum:看到这道题两眼放光:“哇这可以用dijkstra最短路径来写”。心情激动地写下了第一次dijkstra的实现..然后运行时间被DP暴捶…

    • def dijkstra(self,grid):
              result = 0
              m = len(grid)
              n = len(grid[0])
              if m==0 or n ==0:
                  return 0
              traversed = {}
              untraversed  = {}
              traversed[(0,0)] = [grid[0][0],False]
              for i in range(m):
                  for j in range(n):
                      untraversed[(i,j)] = float("inf")
              del untraversed[(0,0)]
              i,j=0,0
              while len(untraversed)>0:
                  for key,value in traversed.items():
                      if not value[1]:
                          if key[0] <m-1:
                              if (key[0]+1,key[1]) not in traversed:
                                  traversed[(key[0]+1,key[1])]= [grid[key[0]+1][key[1]]+traversed[key][0],False]
                                  del untraversed[(key[0]+1,key[1])]
                              elif traversed[(key[0]+1,key[1])][0] > grid[key[0]+1][key[1]]+traversed[key][0]:
                                  traversed[(key[0]+1,key[1])][0]= grid[key[0]+1][key[1]]+traversed[key][0]
                          if key[1] <n-1:
                              if (key[0],key[1]+1) not in traversed:
                                  traversed[(key[0],key[1]+1)]= [grid[key[0]][key[1]+1]+traversed[key][0],False]
                                  del untraversed[(key[0],key[1]+1)]
                              elif traversed[(key[0],key[1]+1)][0] > grid[key[0]][key[1]+1]+traversed[key][0]:
                                  traversed[(key[0],key[1]+1)][0]= grid[key[0]][key[1]+1]+traversed[key][0]
                          traversed[key][1] = True
              return traversed[(m-1,n-1)][0]
      
    • def dp(self,grid):
      	m = len(grid)
              n = len(grid[0])
              for i in range(1, n):
                  grid[0][i] += grid[0][i-1]
              for i in range(1, m):
                  grid[i][0] += grid[i-1][0]
              for i in range(1, m):
                  for j in range(1, n):
                      grid[i][j] += min(grid[i-1][j], grid[i][j-1])
              return grid[-1][-1]
      

其实说到底对于这个题,这两种写法思想是一致的。但是显然DP看到了问题本质,每一个点的值只与←和↑两个值有关。第一种dijkstra的实现并没有抓到这个本质,又加上过多访存和字典增删的开销,导致时间大大超出DP

  • 经典题:通过二叉树的前序和中序遍历,画出二叉树
    • 思路:
    • 前序序列队首值,总是一颗树/子树的根
    • 在中序序列中,找到这个队首值的位置。
    • 位于这个位置左边的,就是属于这个根的左子树;右边的,就是右子树
    • 递归,直到inorder为空就返回(inorder为空说明当前节点没有子树了)
  • LC141: Find cycle in a linked list
    • 题目本身很简单,自然的想法是遍历+哈希表
      • 时间复杂度:O(n)
      • 空间复杂度: O(n)
    • 一种空间复杂度为O(1)的方法:两根指针
      • 两根指针同时遍历
      • 一根指针步长设为1
      • 另一根步长设为2
      • 每一次判断两根指针是否指向同一个node