两数之和
第十一章 26题
给一个整数数组,找到两个数使得他们的和等于一个给定的数 target。
你需要实现的函数 twoSum 需要返回这两个数的下标, 并且第一个下标小于第二个下标。注意这里下标的范围是 1 到 n,不是以 0 开头。
样例:
给出 numbers = [2, 7, 11, 15], target = 9, 返回 [1, 2].
// An highlighted block
class Solution(object):
def twoSum(self,nums,target):
for k in range(len(nums)):
for i in range(len(nums)-1,-1,-1):
if nums[k]+nums[i]==target and k!=i:
a=[k,i]
return a
break
if __name__ =="__main__":
x = input("请输入列表: ")
xlist = x.split(",")
xlist = [int(xlist[i]) for i in range(len(xlist))]
a = Solution()
print(a.twoSum(xlist,9))
分析:
给定一个数列(注意不一定有序),和一个指定的数值 target。从这个数列中找出两个数相加刚好等于 target,要求给出这两个数的下标(注意数列下标是从 1 而不是从 0 开始)。
首先将数列排序。由于最后要得求的是两个数的原有下标,而不是两个数本身,因此要用一个新的对象 Item 来封装原有数列元素,并记录该元素的原有下标。排序是针对数列元素本身数值的,分别用
一个index1指针和一个index2指针指向排序后的数列的首位,如果指向的两个数相加的和等于target,则搜索结束;如果和小于target,则由于 index2 此时指向的已经是数组中的最大数了,因此只能令index1 向右移动一次;如果和大于 target,则由于此时 index1 已经指向数组中的最小数了,因此只能令 index2 向左移动一次。用一个循环重复上述过程,直到和等于 target 宣告搜索成功,或者index1>=index2 宣告搜索失败。
空间复杂度 O(n),因为构造了一个新的 Item 序列。时间复杂度方面,如果假设 Python 的 sort 算法是用的快速排序的话,那排序的时间复杂度为 O(nlogn),搜索过程的时间复杂度为 O(n),因此总的时间复杂度为 O(nlogn)。
----2020/3/15
----一个栈的初始状态为空。现将元素1,2,3,A,B,C依次入栈,然后再依次出栈,则元素出栈的顺序是
正确答案: C
1,2,3,A,B,C
C,B,A,1,2,3
C,B,A,3,2,1
1,2,3,C,B,A
解析:栈的修改是按后进先出的原则进行的。
----设有四个元素A、B、C、D顺序进栈,在进栈过程中可以出栈,出栈次序错误的排列是
正确答案: F
ABCD
DCBA
ACBD
BCDA
ACDB
DCAB
解析:A:A进A出,B进B出,C进C出,D进D出。
B:ABCD依次进入,DCBA依次输出。
C:A进A出,BC进CB出,D进D出。
D:A进,B进B出,C进C出,D进D出,A出。
E:A进A出,B进,C进C出,D进D出,B出。
----下列情况中,不能使用栈(stack)来解决问题的是?
正确答案: D
将数学表达式转换为后辍形式
实现递归算法
高级编程语言的过程调用
操作系统分配资源(如CPU)
解析:对于操作系统中CPU的资源分配是根据时间片来轮流分配的。
----用俩个栈模拟实现一个队列,如果栈的容量分别是O和P(O>P),那么模拟实现的队列最大容量是多少?
正确答案: C
O+P
2O+1
2P+1
2O-1
解析:
----一个空栈,如果有顺序输入:a1,a2,a3。。。an(个数大于3),而且输出第一个为an-1,那么所有都出栈后,()
正确答案: D
输出的最后元素一定为an
输出的最后元素一定为a1
不能确定元素a1~an-2在输出顺序
an-2一定比an-3先出
解析:既然an-1先出栈,说明 an-2, an-3已经入栈并且还未出栈,所以D肯定是对的。
----2020/3/16
----题目来源于王道论坛
下列关于栈的叙述中,错误的是 。
Ⅰ.采用非递归方式重写递归程序时必须使用栈
Ⅱ.函数调用时,系统要用栈保存必要的信息
Ⅲ.只要确定了入桟次序,即可确定出栈次序
Ⅳ.栈是一种受限的线性表,允许在其两端进行操作
正确答案: C
仅 I
仅I、Ⅱ、Ⅲ
仅I、Ⅲ、Ⅳ
仅Ⅱ、Ⅲ、Ⅳ
解析:I的反例:计算斐波拉契数列迭代实现只需要一个循环即可实现。Ⅲ的反例:入栈序列为1、2,进行如下操作PUSH、PUSH、POP、POP,出栈次序为2、1;进行如下操作PUSH、POP、PUSH、POP,出栈次序为1、2。Ⅳ,栈是一种受限的线性表,只允许在一端进行操作。Ⅱ正确。
----栈是先进后出的数据结构。给定一个大小为3的初始状态为空的栈,已知一组数据经过这个栈后,最终的数据顺序依次为:1 3 2 4 ,问原始的进栈数据不可能是以下的那组?
正确答案: C
2 3 1 4
1 4 2 3
4 2 3 1
3 1 2 4
解析:链接:https://www.nowcoder.com/questionTerminal/da4b46be6f7c4be59f588a3d4aaf5bae
来源:牛客网
A push 2, push 3, push 1, pop 1, pop 3, pop 2, push 4, pop4 可得到1 3 2 4;
B push 1, pop 1, push 4, push 2, push 3, pop 3, pop 2, pop 4 可得;
C 想要首先弹出1,需要将4 2 3 1 四个数全部压栈,但是栈大小为3,所以不可能;
D push 3,push 1,pop 1,pop 3,push 2,pop 2, push 4, pop 4可得。
----一个栈的入栈序列为1,2,3,…,n ,其出栈序列是 p 1 ,p 2 ,p 3 ,…p n 。若p 2 = 3,则 p 3 可能取值的个数是()
正确答案: C
n-3
n-2
n-1
无法确定
解析:最简单的举例子:
n=3
–>1,2,3
–>p1,p2,p3 p2=3
所有可能情况:
1 2 3
1 3 2
2 1 3
2 3 1
3 2 1
==>n=3时答案为2
----一个栈的输入序列为连续整数1,2,3…n,若输出序列的第一个元素是n,输出第 i(1<=i<=n)个元素是( )。
正确答案: B
不确定
n-i+1
I
N-i
解析:若输出序列的第一个元素是n”这句话隐含的意思是:所有元素全入栈了,再依次出栈,所以第i个出栈的是n-i+1
----设栈的存储空间为 S(1:60) ,初始状态为 top=61 。现经过一系列正常的入栈与退栈操作后, top=1 ,则栈中的元素个数为( )
正确答案: A
60
59
0
1
解析:栈是一种特殊的线性表,它所有的插入与删除都限定在表的同一端进行。入栈运算即在栈顶位置插入一个新元素,退栈运算即取出栈顶元素赋予指定变量。栈为空时,栈顶指针 top=0 ,经过入栈和退栈运算,指针始终指向栈顶元素。初始状态为 top=61 ,当 top=1 时,元素依次存储在单元 1 : 60 中,个数为 60 。
----下列数据结构具有记忆功能的是?
正确答案: C
队列
循环队列
栈
顺序表
解析:栈按照“先进后出”(FILO)或“后进先出”(LIFO)组织数据,栈具有记忆作用。
----2020/5/6
----下列叙述中正确的是?
正确答案: A
线性表是线性结构;
栈与队列是非线性结构;
线性链表是非线性结构;
二叉树是线性结构
解析:数据的逻辑结构分为线性结构和非线性结构。
常用的线性结构有:线性表,栈,队列,双队列,数组,串。
常见的非线性结构有:二维数组,***数组,广义表,树(二叉树等),图,堆。
----下列叙述中正确的是( )
正确答案: A
在栈中,栈顶指针的动态变化决定栈中元素的个数
在循环队列中,队尾指针的动态变化决定队列的长度
在循环链表中,头指针和链尾指针的动态变化决定链表的长度
在线性链表中,头指针和链尾指针的动态变化决定链表的长度
解析:在栈中,栈底指针保持不变,有元素入栈,栈顶指针增加,有元素出栈,栈顶指针减少。
在循环队列中,队头指针和队尾指针的动态变化决定队列的长度。
在循环链表中,前一个结点指向后一个结点,而最后一个结点指向头结点,只有头结点是固定的。
线性链表中,由于前一个结点包含下一个结点的指针,尾结点指针为空,要插入或删除元素,只需要改变相应位置的结点指针即可,头指针和尾指针无法决定链表长度。
故本题答案为 A 选项。
----若栈采用链式存储结构,则下列说法中正确的是()
正确答案: D
需要判断栈满但不需要判断栈空
不需要判断栈满也不需要判断栈空
需要判断栈满且需要判断栈空
不需要判断栈满但需要判断栈空
解析:链栈由于采用了链表的方式作为存储方式,入栈时,使用malloc申请空间后,用指针相连接,所以节点个数没有限制,但是出栈时,如果栈中的元素个数为0,则不能继续出栈,所以需要判断当前栈是否为空
----2020/5/7
----中序遍历二叉链存储的二叉树时,一般要用堆栈;中序遍历检索二叉树时,也必须使用堆栈()
正确答案: B
对
错
解析:二叉链存储法也叫孩子兄弟法,左指针指向左孩子,右指针指向右兄弟。而中序遍历的顺序是左孩子,根,右孩子。这种遍历顺序与存储结构不同,因此需要堆栈保存中间结果。
而中序遍历检索二叉树时,由于其存储结构跟遍历顺序相符,因此不需要用堆栈。
----设栈的初始状态为空,当字符序列a3_作为栈的输入时,输出长度为3的且可以用作C语言标识符的字符串序列有()个。
正确答案: C
4
6
3
5
解析:
----设输入序列是1,3,5…m,经过栈的作用后输出序列的第一个元素是m,则输出序列中第i个输出元素是()
正确答案: A
m-2(i-1)
m-i
m-1-i
m+1-i
解析:
----
正确答案: B
解析:--------
----以下哪个选项中可能应用到栈。
正确答案: A B C D
递归
快速排序(非递归程序用栈实现)
表达式求值
树的遍历
解析:A,递归肯定用到栈的,存放局部变量,返回地址等,不过该栈是操作系统提供的栈。
B,快速排序的非递归实现,栈中存放要进行一遍快排的起始位置,利用栈先进后出的方式,模拟递归的过程。
C,表达式求值,将中序表达式转换为前序或后序时,需要用栈存放符号。
D,树的深度优先遍历,用栈记录遍历过的元素,以便进行回溯。
----在表结构中最常用的是线性表,栈和队列不太常用。请问这句话的说法是正确的吗?
正确答案: B
正确
错误
解析:栈和队列也是线性表
线性表是最基本、最简单、也是最常用的一种数据结构。
----递归式的先序遍历一个n节点,深度为d的二叉树,需要栈空间的大小为______。
正确答案: B
O(n)
O(d)
O(logn)
O(nlogn)
解析:因为二叉树并不一定是平衡的,也就是深度d!=logn,有可能d>>logn。。所以栈大小应该是O(d)
----在Windows中,下列关于堆和栈的说法中错误的是?
正确答案: B
堆都是动态分配的,没有静态分配的堆;栈有静态分配和动态分配2种分配方式。
堆的生长方向是向下的,即向着内存地址减小的方向增长;栈的生长方向是向上的,即向着内存地址增加的方向增长。
对堆的频繁new/delete会造成内存空间的不连续,从而造成大量的碎片;栈则不会存在这个问题
栈是由编译器自动治理;堆的释放工作由程序员控制,轻易产生内存泄露。
解析:1、栈区(stack)由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
2、堆区(heap)一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事。
区别:
- 管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生内存溢出。
- 空间大小:堆内存几乎是没有什么限制。栈一般都是有一定的空间大小。
- 碎片问题:对于堆来讲,频繁的new/delete会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题。
- 分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。
- 分配效率:栈的效率比较高。堆的效率比栈要低得多。
- 增长方向:堆的增长方向是从程序低地址到高地址向上增长,而栈的增长方向刚好相反(实际情况可能不是这样的,与CPU的体系结构有关)
----下面的一些说法哪些是正确的:( )
正确答案: B C
缓存策略中基于LRU的淘汰策略,在缓存满时,会把最近进入缓存的数据先淘汰,以保持高的命中率
中缀表达式A+(B+C)*D的后缀表但式为:ABC+D * +
堆栈是一种LIFO的数据结构
高级语言通过编译或者即时编译(JIT)后成为汇编语言被机器装载执行
TCP协议和UDP协议都在IP协议之上,TCP是面向连接的,UDP是面向非连接的,但无论TCP还是UDP建立通信都需要一次握手,以确保对方的端口已经打开
现代的操作系统一般都分为用户态和内核态,用户态和内核态的切换是经常发生的,程序员不需要对内核态和用户态的切换进行编程关注
解析:A: 刚好说反了,LRU的过程如下(其实很好理解,访问的频率越高越不该丢弃):
1. 新数据插入到链表头部;
2. 每当缓存命中(即缓存数据被访问),则将数据移到链表头部;
3. 当链表满的时候,将链表尾部的数据丢弃。
B: 有种简单的方法:
1. 先将中缀表达式加括号:(A + ((B + C) * D));
2. 再把运算符移到括号后面(前缀移到前面):(A ((B C)+ D) * )+;
3. 把括号去掉:ABC+D*+。
C: LIFO:Last In First Out(后进先出)。
D: 汇编语言也并不能被机器执行,机器可以执行的是二进制的机器语言。
E: TCP建立通信需要三次握手,而UDP,在传送数据前不需要先建立连接,远地的主机在收到UDP报文后也不需要给出任何确认。
F: 程序员是可以通过调用fork()函数的方式进行切换的。
----设栈采用顺序存储结构,若已有i-1个元素入栈,则将第i个元素入栈时,入栈算法的时间复杂性为O(i)()
正确答案: B
对
错
解析:相当于在数组最后插多一个 o(1)
----
正确答案: D
解析:第一步:按照运算符的优先级对所有的运算单位加括号:式子变成了:((a+(b * c))-(d+e))
第二步:转换前缀与后缀表达式
前缀:把运算符号移动到对应的括号前面
则变成了:-( +(a * (bc)) +(de))
把括号去掉:-+a * bc+de 前缀式子出现
后缀:把运算符号移动到对应的括号后面
则变成了:((a(bc)* )+ (de)+ )-
把括号去掉:abc*+de± 后缀式子出现
----若栈采用顺序存储方式存储,现两栈共享空间 V[1 m] , top[1] 、 top[2] 分别代表第 1 和第 2 个栈的栈顶,栈 1 的底在 V[1] ,栈 2 的底在 V[m] ,则栈满的条件是 。
正确答案: B
|top[2]-top[1]|=0
top[1]+1=top[2]
top[1]+top[2]=m
top[1]=top[2]
解析:假设m=10
栈1增加8个元素,此时top[1]=8
栈2增加2个元素,此时top[2]=9
栈满,但是top[2]+top[2]=17≠m=10
而top[1]+1=top[2]
----解析XML时,需要校验节点是否闭合,如必须有与之对应,用()数据结构实现比较好()
正确答案: D
链表
树
队列
栈
解析:栈是解决封闭对应问题的有效方法。
比如在解析XML中,遇到一个标签(左标签)就入栈,遇到其子标签的左标签(如)同样入栈。遇到右标签(如或)就校验栈顶标签是否与该右标签对应,能对应就出栈,不能对应则说明标签不对称,是无效的XML文件。