文章目录

  • 一、选择题
  • 二、编程题


一、选择题

1、在单链表中,要将s所指结点插入到p所指结点之后,其语句应为(D )
A. s.next=p+1; p.next=s;
B. p.next=s; s.next=p.next
C. s.next=p.next; p.next=s.next;
D. s.next=p.next; p.next=s;
答案解析:D
把s指向的结点插入到p所指向的结点之后,首先要保证链表不断链,就需要先把s指向的结点和p后年的结点链接起来,代码为
s.next=p.next;
最后让p的下一个结点指向s即可,代码为p.next=s
2、下述有关栈和队列的区别,说法错误的是 (D )
A. 栈是限定只能在表的一端进行插入和删除操作。
B. 队列是限定只能在表的一端进行插入和在另一端进行删除操作。
C. 栈和队列都属于线性表
D. 栈的插入操作时间复杂度都是o(1),队列的插入操作时间复杂度是o(n)
答案解析:D
栈的插入操作时间复杂度都是o(1),因为栈只允许在表的某一端进行操作
队列的插入操作时间复杂度是o(1),队列的入队操作也只允许在表的其中一端
3、输入序列是ABC,输出序列变为BCA时,经过的栈操作为(B )
A. push,push,push,pop,pop,pop
B. push,push,pop,push,pop,pop
C. push,pop,push,push,pop,pop
D. push,push,pop,pop,push,pop
答案解析:B
上题中,整个入栈和出栈的过程可以为,A先入栈(push),B入栈(push),B出栈(pop),C入栈(push),C出栈
(pop),A出栈(pop),所以整个过程为:push,push,pop,push,pop,pop
4、栈的特点是先入先出,这种说法(B )
A. 正确 B. 错误
答案解析:B
说法错误。栈的特点为先入后出
5、一个队列的入队序列为 1234 ,则队列可能的输出序列是(A )
A. 4321
B. 1234
C. 1432
D. 3241
答案解析:B
队列的特点是先入先出原则,入队顺序为1234,那么出队顺序和入队顺序是一样的

二、编程题

1、合并链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。OJ链接

示例1:
输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]
示例2:
输入:l1 = [], l2 = [0]
输出:[0]

【解题思路】:
这道题目课上反复讲过,一共有两种思路来解决。
1.递归法,利用好方法的语义,判断当前l1和l2的头结点的大小,将剩余结点和另外整个链表的合并操作交给子函数处理。
2.原地移动,在遍历l1和l2的时候尾插新的合并链表。

class Solution {
// 1.递归法
	public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
		if (list1 == null) {
			return list2;
		}
		if (list2 == null) {
			return list1;
		}
		if (list1.val <= list2.val) {
		// 说明此时要把list1.next和整个list2交给merge
		// 然后将结果拼接到list1.next
		list1.next = mergeTwoLists(list1.next,list2);
		return list1;
		}else {
			list2.next = mergeTwoLists(list1,list2.next);
			return list2;
		}
	}
	// 2.原地移动
	public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
		// 边界
		if (list1 == null) {
			return list2;
		}
		if (list2 == null) {
			return list1;
		}
		// 此时l1和l2都不为空
		ListNode dummyHead = new ListNode(101);
		ListNode last = dummyHead;
		while (list1 != null && list2 != null) {
			if (list1.val <= list2.val) {
				last.next = list1;
				last = list1;
				list1 = list1.next;
			}else {
				last.next = list2;
				last = list2;
				list2 = list2.next;
			}
		}
		// 此时l1或l2为空
		if (list1 == null) {
			last.next = list2;
		}else {
			last.next = list1;
		}
		return dummyHead.next;
	}
}

2、删除链表中重复的结点
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表 1->2->3->3->4->4->5 处理后为 1->2->5 OJ链接

示例1:
输入:{1,2,3,3,4,4,5}
返回值:{1,2,5}
示例2:
输入:{1,1,1,8}
输出:{8}

【解题思路】:
这道题难点有两个。1.如何判断重复结点(使用cur和next引用来判断),prev一定指向待删除结点的前驱(prev一定不是
待删除的结点)。2.删除多个重复结点(prev.next = next).

public class Solution {
	public ListNode deleteDuplication(ListNode pHead) {
		ListNode dummyHead = new ListNode(-1);
		dummyHead.next = pHead;
		ListNode prev = dummyHead;
		ListNode cur = prev.next;
		while (cur != null) {
			ListNode next = cur.next;
			if (next == null) {
			// 当前链表只有一个结点
				return dummyHead.next;
			}else {
				if (cur.val != next.val) {
					prev = prev.next;
					cur = cur.next;
				}else {
					while (next != null && cur.val == next.val) {
							next = next.next;
					}
					// 此时next指向第一个不重复的结点
					prev.next = next;
					cur = next;
				}
			}
		}
		return dummyHead.next;
	}
}