文章目录
- 一、选择题
- 二、编程题
一、选择题
1、线性结构的是【多选】(A B C )
A. 数组
B. 链式存储栈
C. 顺序存储栈
D. 顺序存储二叉树
答案解析:A B C
数组,链表,栈,队列都属于线性结构;
二叉树属于非线性结构。
2、有一个单向链表,头指针和尾指针分别为p,q,以下哪项操作的复杂度不受链表长度的影响【多选】(A C D )
A. 删除头部元素
B. 删除尾部元素
C. 头部元素之前插入一个元素
D. 尾部元素之后插入一个元素
答案解析:A C D
删除头部元素的代码为:p=p.next;
删除链表的尾部元素:需要先定义一个指针head指向链表的头结点,然后移动head至尾结点的前一个结点,令head.next=null,即可删除尾结点,如果链表越长,那么head移动的长度越多;
头部元素之前插入一个元素:设插入的元素为c,那代码为c.next=p,即可插入,头结点为c;
尾部元素之后插入一个元素:设插入的元素为c,代码为q.next=c;
3、在一个单链表中,p、q分别指向表中两个相邻的结点,且q所指结点是p所指结点的直接后继,现要删除q所指结点,可用的语句是 (C )
A. p=q.next
B. p.next=q
C. p.next=q.next
D. q.next=NULL
答案解析:C
通过题意得知,q结点在p结点后面,要删除q结点的话只需要让q的前一个结点p指向q结点的后一个结点;
代码为p.next=q.next;
4、在一个具有 n 个结点的有序单链表中插入一个新结点并仍然保持有序的时间复杂度是 ( B)
A. O(1)
B. O(n)
C. O(n2)
D. O(nlog2n)
答案解析:B
时间复杂度是求算法在最坏的情况
本题中最欢情况是要插入的新结点在链表的尾部,需要移动n次,到链表尾部才可以成功插入;所以时间复杂度为O(n)
5、对链表进行插入和删除操作时不必移动链表中结点。(A )
A. 正确
B. 错误
答案解析:A
链表的各个结点之间是通过指针连接的,所以要删除或者插入某一个结点的话,只需要改变链表相关结点的指针即可。
二、编程题
1、排序链表
给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。OJ链接
示例1:
输入:head = [4,2,1,3]
输出:[1,2,3,4]
示例2:
输入:head = [-1,5,3,4,0]
输出:[-1,0,3,4,5]
思路:用归并排序的思路,先不断分割,知道每个子区间只有一个节点位置,然后开始合并。
class Solution {
public ListNode sortList(ListNode head) {
return toSortList(head, null);
}
public ListNode toSortList(ListNode head, ListNode tail) {
if (head == null) {
return head;
}
if (head.next == tail) {
head.next = null;
return head;
}
ListNode slow = head, fast = head;
while (fast != tail) {
slow = slow.next;
fast = fast.next;
if (fast != tail) {
fast = fast.next;
}
}
ListNode mid = slow;
ListNode list1 = toSortList(head, mid);
ListNode list2 = toSortList(mid, tail);
ListNode sorted = merge(list1, list2);
return sorted;
}
public ListNode merge(ListNode head1, ListNode head2) {
ListNode dummyHead = new ListNode(0);
ListNode temp = dummyHead, temp1 = head1, temp2 = head2;
while (temp1 != null && temp2 != null) {
if (temp1.val <= temp2.val) {
temp.next = temp1;
temp1 = temp1.next;
} else {
temp.next = temp2;
temp2 = temp2.next;
}
temp = temp.next;
}
if (temp1 != null) {
temp.next = temp1;
} else if (temp2 != null) {
temp.next = temp2;
}
return dummyHead.next;
}
}
2、奇偶链表
给定一个单链表,把所有的奇数节点和偶数节点分别排在一起。请注意,这里的奇数节点和偶数节点指的是节点编号
的奇偶性,而不是节点的值的奇偶性。OJ链接
示例1:
输入: 1->2->3->4->5->NULL
输出: 1->3->5->2->4->NULL
示例2:
输入: 2->1->3->5->6->4->7->NULL
输出: 2->3->6->7->1->5->4->NULL
【解题思路】:
如果链表为空,则直接返回链表。
对于原始链表,每个节点都是奇数节点或偶数节点。头节点是奇数节点,头节点的后一个节点是偶数节点,相邻节点的奇偶性不同。因此可以将奇数节点和偶数节点分离成奇数链表和偶数链表,然后将偶数链表连接在奇数链表之后,合并后的链表即为结果链表。
原始链表的头节点 head 也是奇数链表的头节点以及结果链表的头节点,head 的后一个节点是偶数链表的头节点。
令 evenHead = head.next,则 evenHead 是偶数链表的头节点。
维护两个指针 odd 和 even 分别指向奇数节点和偶数节点,初始时 odd = head,even = evenHead。通过迭代的方式将奇数节点和偶数节点分离成两个链表,每一步首先更新奇数节点,然后更新偶数节点。
更新奇数节点时,奇数节点的后一个节点需要指向偶数节点的后一个节点,因此令 odd.next = even.next,然后令 odd = odd.next,此时 odd 变成 even 的后一个节点。
更新偶数节点时,偶数节点的后一个节点需要指向奇数节点的后一个节点,因此令 even.next = odd.next,然后令 even = even.next,此时 even 变成 odd 的后一个节点。
在上述操作之后,即完成了对一个奇数节点和一个偶数节点的分离。重复上述操作,直到全部节点分离完毕。全部节点分离完毕的条件是 even 为空节点或者 even.next 为空节点,此时 odd 指向最后一个奇数节点(即奇数链表的最后一个节点)。
最后令 odd.next = evenHead,将偶数链表连接在奇数链表之后,即完成了奇数链表和偶数链表的合并,结果链表的头节点仍然是 head。
class Solution {
public ListNode oddEvenList(ListNode head) {
if(head==null){
return head;
}
ListNode evenHead=head.next;
ListNode odd=head,even=evenHead;
while(even!=null&&even.next!=null){
odd.next=even.next;
odd=odd.next;
even.next=odd.next;
even=even.next;
}
odd.next=evenHead;
return head;
}
}