算法(23)-leetcode-剑指offer7

leetcode-剑指offer-5

  • 59.面试题59-队列的最大值
  • 60.面试题64-求1+2+...+n
  • 61.面试题65-不用加减乘除做加法
  • 62.面试题66-构建乘积数组
  • 63.面试题68-1二叉树搜索树的最近公共祖先
  • 64.面试题68-2二叉树的最近公共祖先
  • 65.面试题67-把字符串转换成数字-自动机
  • 66.面试题20-表示数值的字符串-自动机

本系列博文为题库刷题笔记,(仅在督促自己刷题)如有不详之处,请参考leetcode官网:https://leetcode-cn.com/problemset/lcof/

59.面试题59-队列的最大值

请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value、push_back 和 pop_front 的均摊时间复杂度都是O(1)。

若队列为空,pop_front 和 max_value 需要返回 -1

思路1:直接定义一个队列,

import Queue
class MaxQueue(object):def __init__(self):self.deque=Queue.deque()def max_value(self):""":rtype: int"""return max(self.deque) if self.deque else -1def push_back(self, value):""":type value: int:rtype: None"""self.deque.append(value)def pop_front(self):""":rtype: int"""return self.deque.popleft() if self.deque else -1

时间复杂度:插入操作o(1),删除操作o(1),取最大值o(n)

思路2:维护一个辅助双端队列,用于存储最大值,每次插入元素时,将辅助双端队列的尾部小于插入元素的值去除,然后加入该元素。每次弹出队列头部时,比较弹出元素与辅助队列的头是否一致,如果一致,更新双端队列头部( 弹出该头部)

import Queue
class MaxQueue(object):def __init__(self):self.helper=Queue.deque()   # deque[0] 最大值,deque[-1]最小值self.queue=Queue.Queue()def max_value(self):""":rtype: int"""return self.helper[0] if self.helper else -1def push_back(self, value):""":type value: int:rtype: None"""while(self.helper and self.helper[-1]<value):self.helper.pop()    # 弹出双端队列尾部的元素self.helper.append(value) # 在双端队列尾部加入元素self.queue.put(value)  # 在队列尾加入元素def pop_front(self):""":rtype: int"""if not self.helper:  # 为什么要是helper queue不行return -1ans=self.queue.get()  # 弹出队列头if ans==self.helper[0]:self.helper.popleft()  # 双端队列弹出队列头部元素return ans
# Your MaxQueue object will be instantiated and called as such:
# obj = MaxQueue()
# param_1 = obj.max_value()
# obj.push_back(value)
# param_3 = obj.pop_front()

时间复杂度:删除o(1),最大o(1),求最大值:均摊时间复杂度o(1),做一个插入操做最多会有n次出队操作,但是每个数字只会出队一次,所以维护n个元素最大值的总出队操作也就是n,即均摊时间复杂度为0(1)。

60.面试题64-求1+2+…+n

求 1+2+…+n ,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。

思路1:求和公式,使用到了乘除法,不可用
1+2+3,...,n=(1+n)∗n/21+2+3,...,n=(1+n)*n/21+2+3,...,n=(1+n)n/2

思路2:迭代要使用循环语句,不可

思路3:递归,递归出口时需要用到判断语句,但是判断语句可以使用逻辑运算符的短路作用,开启递归或结束递归:
n>1andsumNums(n−1)n>1 \ \ and \ \ sumNums(n-1)n>1  and  sumNums(n1)

当n>1 时会开启下一层递归,当n=1,不执行递归,执行之后的操作

class Solution(object):def __init__(self):self.res=0def sumNums(self, n):""":type n: int:rtype: int"""def rec(num):num>1 and rec(num-1)self.res+=numrec(n)return self.res

61.面试题65-不用加减乘除做加法

写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号。
思路:不用加减乘除做加法,借助位运算。
经过观察可以发现,两个数字的二进制和,对应位置上的结果运算规律和异或一致,进位位置上的结果和and运算相同。将两数异或 的结果和and 的结果相加,等价于求原来两个数字的和。又出现两数求和操作,重复两数求和求异或。直至进位为0,不存在加法操作。
注意点:python 中的数字以补码的形式存储,python中的数字没有长度,依据题目要求,需要舍去大于32位以上的数字。
补码还原:~(a^x)

class Solution(object):def add(self, a, b):""":type a: int:type b: int:rtype: int"""x = 0xffffffffa, b = a & x, b & xwhile b != 0:a, b = (a ^ b), (a & b) << 1 & xreturn a if a <= 0x7fffffff else ~(a ^ x)

62.面试题66-构建乘积数组

给定一个数组 A[0,1,…,n-1],请构建一个数组 B[0,1,…,n-1],其中 B 中的元素 B[i]=A[0]×A[1]×…×A[i-1]×A[i+1]×…×A[n-1]。不能使用除法。
思路:暴力解法43/44时间超出限制

class Solution(object):def constructArr(self, a):""":type a: List[int]:rtype: List[int]"""n=len(a)b=[1]*nfor i in range(n):for j in range(n):if j!=i:b[i]*=a[j]return b

思路2:左右乘积数组
l[i]=a[0]*…a[i-1]
r[i]=a[i+1]*…a[n-1]

在这里插入代码片class Solution(object):def constructArr(self, a):""":type a: List[int]:rtype: List[int]"""n=len(a)b=[1]*nleft=[1]*nright=[1]*nfor i in range(1,n):left[i]=left[i-1]*a[i-1]for i in range(n-2,-1,-1):right[i]=right[i+1]*a[i+1]for i in range(n):b[i]=left[i]*right[i]return b

63.面试题68-1二叉树搜索树的最近公共祖先

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

思路:一个节点为最近祖先:pq 在该节点的两棵子树/p=root 或者q=root。

首先判断 p 和 q 是否相等,若相等,则直接返回 p 或 q 中的任意一个,程序结束
若不相等,则判断 p 和 q 在向左还是向右的问题上,是否达成了一致
如果 p 和 q 都小于root, 哥俩一致认为向左👈,则 root = root.left
如果 p 和 q 都大于root, 哥俩一致认为向右👉,则 root = root.right
如果 p 和 q 哥俩对下一步的路线出现了分歧,说明 p 和 q 在当前的节点上就要分道扬镳了,当前的 root 是哥俩临别前一起走的最后一站
返回当前 root
迭代:

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution(object):def lowestCommonAncestor(self, root, p, q):""":type root: TreeNode:type p: TreeNode:type q: TreeNode:rtype: TreeNode"""if root==None:return rootif p.val==q.val:return pnode=rootwhile(node):if node.val>p.val and node.val>q.val:node=node.leftelif node.val<p.val and node.val<q.val:node=node.rightelse:return node

递归:

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = Noneclass Solution(object):def lowestCommonAncestor(self, root, p, q):""":type root: TreeNode:type p: TreeNode:type q: TreeNode:rtype: TreeNode"""if root.val<p.val and root.val<q.val:return self.lowestCommonAncestor(root.right,p,q)if root.val>p.val and root.val>q.val:return self.lowestCommonAncestor(root.left,p,q)return root

64.面试题68-2二叉树的最近公共祖先

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

思路1:记录父亲节点
先遍历一遍树,记录每个点的父亲节点。然后去找从p开始去找其父亲节点路径:vis_has,接着从q开始去找其父亲,在vis_hash 中第一次出现的就为最近公共祖先。

class Solution(object):def lowestCommonAncestor(self, root, p, q):""":type root: TreeNode:type p: TreeNode:type q: TreeNode:rtype: TreeNode"""def dfs(node):if node==None:returnif node.left:fa_hash[node.left]=nodeif node.right:fa_hash[node.right]=nodedfs(node.left)dfs(node.right)fa_hash={root:None}vis_hash={}dfs(root)        while (p!=None):# print(p)vis_hash[p]=True     # 要记得把自己放进去p=fa_hash[p]while(q!=None):if vis_hash.get(q):  # 记得自己也要验证return qq=fa_hash[q]

思路2:递归 从叶子节点往上递归,找到一个节点,其左右子树中包含p或者q,该节点为最近的父亲节点。

class Solution(object):def __init__(self):self.res=Nonedef lowestCommonAncestor(self, root, p, q):""":type root: TreeNode:type p: TreeNode:type q: TreeNode:rtype: TreeNode"""def dfs(node,p,q):if node==None:return Falseleft=dfs(node.left,p,q)right=dfs(node.right,p,q)mid=(p==node or q==node)if mid+left+right==2:self.res=nodereturn mid or left or rightdfs(root,p,q)return self.res

65.面试题67-把字符串转换成数字-自动机

字符串处理相关的题目往往涉及复杂的流程以及条件情况,如果直接上手写程序,一不小心就会写成及其臃肿的代码。

因此,为了有条理的分析每一个输入字符的处理方法。可以使用自动机方法

程序在每一个时刻有一个状态s,每次总序列中输入一个字符串c ,并根据字符串c 转到下一个状态s’ .我们要做的就是简历一个覆盖所有情况的从s 与c 的映射到s‘ 的表格。

用表格来表示自动机:
表格的第一列为状态,第一行为输入,表格体内部为下一个状态。

在这里插入图片描述
编程时,将状态转换表转换进代码里。

题目要求,输出处转换后的数字。因此在s’=in_number 时,更新我们的输入数字,即可得到最终的答案。

INT_MAX = 2 ** 31 - 1
INT_MIN = -2 ** 31class Automaton:def __init__(self):self.state = 'start'self.sign = 1self.ans = 0self.table = {'start': ['start', 'signed', 'in_number', 'end'],'signed': ['end', 'end', 'in_number', 'end'],'in_number': ['end', 'end', 'in_number', 'end'],'end': ['end', 'end', 'end', 'end'],}def get_col(self, c):if c.isspace():return 0if c == '+' or c == '-':return 1if c.isdigit():return 2return 3def get(self, c):self.state = self.table[self.state][self.get_col(c)]if self.state == 'in_number':self.ans = self.ans * 10 + int(c)self.ans = min(self.ans, INT_MAX) if self.sign == 1 else min(self.ans, -INT_MIN)elif self.state == 'signed':self.sign = 1 if c == '+' else -1class Solution:def strToInt(self, str):automaton = Automaton()for c in str:automaton.get(c)return automaton.sign * automaton.ans

66.面试题20-表示数值的字符串-自动机

请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100"、“5e2”、"-123"、“3.1416”、“0123"都表示数值,但"12e”、“1a3.14”、“1.2.3”、“±5”、"-1E-16"及"12e+5.4"都不是。

自动机解题:
1.画状态转移图
2.列状态转移表
3.确定输入字符串对应的列
4.迭代所有的输入,进行状态转移,如果遇到不合理状态就返回

class Solution(object):def isNumber(self, s):""":type s: str:rtype: bool"""if not s:return FalsetransTable=[[1,2,7,-1,-1,0],[-1,2,7,-1,-1,-1],[-1,2,3,4,-1,9],[-1,3,-1,4,-1,9],[6,5,-1,-1,-1,-1],[-1,5,-1,-1,-1,9],[-1,5,-1,-1,-1,-1],[-1,8,-1,-1,-1,-1],[-1,8,-1,4,-1,9],[-1,-1,-1,-1,-1,9]]cols={"sign":0,"number":1,".":2,"exp":3,"other":4,"blank":5}def get_col(c):if c.isdigit():return "number"elif c in {"+","-"}:return "sign"elif c==".":return "."elif c in {"e","E"}:return "exp"elif c==" ":return "blank"else:return "other"legal_state={2,3,5,8,9}state=0for c in s:state=transTable[state][cols[get_col(c)]]if state==-1:return Falsereturn True if state in legal_state else False

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/444854.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

终于,我读懂了所有Java集合——List篇

ArrayList 基于数组实现&#xff0c;无容量的限制。 在执行插入元素时可能要扩容&#xff0c;在删除元素时并不会减小数组的容量&#xff0c;在查找元素时要遍历数组&#xff0c;对于非null的元素采取equals的方式寻找。 是非线程安全的。 注意点&#xff1a; &#xff08…

终于,我读懂了所有Java集合——queue篇

Stack 基于Vector实现&#xff0c;支持LIFO。 类声明 public class Stack<E> extends Vector<E> {} push public E push(E item) {addElement(item);return item; } pop public synchronized E pop() {E obj;int len size();obj peek();removeElementAt(…

IAP-应用内购买流程

成为ios开发者最大的好处就是&#xff0c;你编写的应用程序会有很多方式可以赚钱。比如&#xff0c;收费版&#xff0c;免费挂广告版&#xff0c;还有就是程序内置购买。 程序内置购买会让你爱不释手&#xff0c;主要有以下原因&#xff1a; 除了程序本身的下载收费以外&#x…

终于,我读懂了所有Java集合——map篇

首先&#xff0c;红黑树细节暂时撸不出来&#xff0c;所以没写&#xff0c;承诺年前一定写 HashMap &#xff08;底层是数组链表/红黑树&#xff0c;无序键值对集合&#xff0c;非线程安全&#xff09; 基于哈希表实现&#xff0c;链地址法。 loadFactor默认为0.75&#xff0…

valgrind工具使用详解

zz自 http://blog.csdn.net/destina/article/details/6198443 感谢作者的分享&#xff01; 一 valgrind是什么&#xff1f; Valgrind是一套Linux下&#xff0c;开放源代码&#xff08;GPL V2&#xff09;的仿真调试工具的集合。Valgrind由内核&#xff08;core&#xff09;以…

网络原理知识点汇总

OSI七层模型 vs. TCP/IP 五层模型&#xff08;有时候也说四层&#xff09;及各层协议 七层&#xff1a;物理层&#xff1a;为数据端设备提供传送数据的通路&#xff0c; IEEE802 数据链路层&#xff1a;提供介质访问和链路管理&#xff0c; ARP&#xff0c;MTU 网络层&#xf…

leetcode516 最长回文子序列

给定一个字符串s&#xff0c;找到其中最长的回文子序列。可以假设s的最大长度为1000。 示例 1: 输入: "bbbab" 输出: 4 一个可能的最长回文子序列为 "bbbb"。 示例 2: 输入: "cbbd" 输出: 2 一个可能的最长回文子序列为 "bb"。 …

社交app应用开发 客户端+服务器源码

原帖地址&#xff1a;http://www.devdiv.com/iOS_iPhone-想学习移动社交APP的童鞋有福了&#xff0c;图文展示&#xff0c;附客户端&#xff0c;服务端源码。-thread-121444-1-1.html 想学习移动社交APP的童鞋有福了&#xff0c;图文展示&#xff0c;附客户端&#xff0c;服务…

leetcode83 删除排序链表中的重复元素

给定一个排序链表&#xff0c;删除所有重复的元素&#xff0c;使得每个元素只出现一次。 示例 1: 输入: 1->1->2 输出: 1->2 示例 2: 输入: 1->1->2->3->3 输出: 1->2->3 思路&#xff1a;判断下一个是否相同即可。 /*** Definition for singl…

leetcode203 移除链表元素

删除链表中等于给定值 val 的所有节点。 示例: 输入: 1->2->6->3->4->5->6, val 6 输出: 1->2->3->4->5 思路&#xff1a;就删呗&#xff0c;注意第一个数可能会被删 /*** Definition for singly-linked list.* public class ListNode {* …

leetcode338 比特位计数

给定一个非负整数 num。对于 0 ≤ i ≤ num 范围中的每个数字 i &#xff0c;计算其二进制数中的 1 的数目并将它们作为数组返回。 示例 1: 输入: 2 输出: [0,1,1] 示例 2: 输入: 5 输出: [0,1,1,2,1,2] 进阶: 给出时间复杂度为O(n*sizeof(integer))的解答非常容易。但你可…

关于房屋的风水学整理

第一步&#xff1a;看缺角&#xff0c;根据户型图的整体形状分析有无缺角户型的形状很多&#xff0c;有三角形的&#xff0c;手枪形的&#xff0c;锯齿型的等等&#xff0c;总的来说缺角就不好&#xff0c;方方正正好&#xff0c;适合“天方地圆”。如下图什么是缺角&#xff0…

leetcode226 反转二叉树

翻转一棵二叉树。 示例&#xff1a; 输入&#xff1a; 4 / \ 2 7 / \ / \ 1 3 6 9 输出&#xff1a; 4 / \ 7 2 / \ / \ 9 6 3 1 备注: 这个问题是受到 Max Howell 的 原问题 启发的 &#xff1a; 谷歌&#xff1a;我们90&#xff05;的…

leetcode234 回文链表

请判断一个链表是否为回文链表。 示例 1: 输入: 1->2 输出: false 示例 2: 输入: 1->2->2->1 输出: true 进阶&#xff1a; 你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题&#xff1f; 思路&#xff1a;逆置前一半&#xff0c;然后从中心出发开始比较即…

leetcode739 每日温度

根据每日 气温 列表&#xff0c;请重新生成一个列表&#xff0c;对应位置的输入是你需要再等待多久温度才会升高超过该日的天数。如果之后都不会升高&#xff0c;请在该位置用 0 来代替。 例如&#xff0c;给定一个列表 temperatures [73, 74, 75, 71, 69, 72, 76, 73]&#…

加速scp传输速度

当需要在机器之间传输400GB文件的时候&#xff0c;你就会非常在意传输的速度了。默认情况下(约125MB带宽&#xff0c;网络延迟17ms&#xff0c;Intel E5-2430&#xff0c;本文后续讨论默认是指该环境)&#xff0c;scp的速度约为40MB&#xff0c;传输400GB则需要170分钟&#xf…

tcpcopy使用方法

1、下载tcpcopy http://code.google.com/p/tcpcopy/downloads/list 2、配置、编译、安装 依此使用如下命令&#xff1a; 配置&#xff1a; ./configure 编译&#xff1a; make 安装&#xff1a; make install 3、使用方法 下面以mosquitto为例&#xff0c;说明tcpcopy的用法&a…

终于,我读懂了所有Java集合——map篇(多线程)

多线程环境下的问题 1.8中hashmap的确不会因为多线程put导致死循环&#xff08;1.7代码中会这样子&#xff09;&#xff0c;但是依然有其他的弊端&#xff0c;比如数据丢失等等。因此多线程情况下还是建议使用ConcurrentHashMap。 数据丢失&#xff1a;当多线程put的时候&…

leetcode82. 删除排序链表中的重复元素 II

给定一个排序链表&#xff0c;删除所有含有重复数字的节点&#xff0c;只保留原始链表中 没有重复出现 的数字。 示例 1: 输入: 1->2->3->3->4->4->5 输出: 1->2->5 示例 2: 输入: 1->1->1->2->3 输出: 2->3 思路&#xff1a;判断n…

leetcode24 两两交换链表中的节点

给定一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后的链表。 你不能只是单纯的改变节点内部的值&#xff0c;而是需要实际的进行节点交换。 示例: 给定 1->2->3->4, 你应该返回 2->1->4->3. 思路&#xff1a;这一看就是个递归定义&…