注:题目来自于《程序员代码面试指南:IT名企算法与数据结构题目最优解》,该书是左程云老师的著作,值得推荐,这里仅是记录一下该书中题目的解法和个人理解
题目一:生成窗口最大值数组
问题描述:
有一个整型数组arr和一个大小为w的窗口从数组的最左边滑到最右边,窗口每次向右边滑一个位置
例如,数组为[4,3,5,4,3,3,6,7],窗口的大小为3时:
4 3 5 4 3 3 6 7 窗口的最大值为5
4 3 5 4 3 3 6 7 窗口的最大值为5
4 3 5 4 3 3 6 7 窗口的最大值为5
4 3 5 4 3 3 6 7 窗口的最大值为4
4 3 5 4 3 3 6 7 窗口的最大值为6
4 3 5 4 3 3 6 7 窗口的最大值为7
如果数组长度为n,创库大小为w,则一共产生n-w+1个窗口的最大值
请实现一个函数
输入:整形数组arr,窗口大小为w
输出:一个长度为n-w+1的数组res,res[i]表示每一种窗口状态下的最大值
以本题为例,结果应该返回{5,5,5,4,6,7}
思路:
可以设计一个辅助双向队列(LinkedList),队首值为滑块中的最大值。遍历数组时先入队,排除队内小于入队值的元素,队内记录位置,不记录值,这样可以判断队中的值何时失效(滑块已经滑过了),失效的值从队首出队,得到的最大值,也从队首出队。
图解:
代码:
public class SlidingWindow {
public static void main(String[] args) {
int[] arr = {4, 3, 5, 4, 3, 3, 6, 7};
int w = 3;
int[] res = getMaxWindow(arr, w);
System.out.println(Arrays.toString(res));
}
private static int[] getMaxWindow(int[] arr, int w) {
// 过滤出一些不符合逻辑的参数
if (arr == null || w < 1 || arr.length < w) {
return null;
}
LinkedList<Integer> qmax = new LinkedList<>();
int[] res = new int[arr.length - w + 1];
int index = 0;
for (int i = 0;i<arr.length;i++){
while (!qmax.isEmpty() && arr[qmax.peekLast()]<= arr[i]){
qmax.pollLast();
}
qmax.addLast(i);
//过期了(滑块已滑过)
if(qmax.peekFirst() == i-w){
qmax.pollFirst();
}if(i >= w-1){
//从滑块开始位置起,每次移动滑块,取队首值
res[index++] = arr[qmax.peekFirst()];
}
}
return res;
}
}
测试结果,亲测可用:
[5, 5, 5, 4, 6, 7]
题目二:打印两个有序链表中的公共部分
题目描述:
给定两个有序链表的头指针head1和head2,打印这两个链表中的公共部分
思路:
因为是有序序列,所以可以比较两个链表头指针的值,值较小的,指针后移,值相等,开始打印链表,值不相等时结束。若head1 或head2有一个移动到null,循环结束
图解:
代码:
链表类:
public class Node {
public int value;
public Node next;
public Node(int data){
this.value = data;
}
}
测试类及代码:
public class CommonPart {
public static void main(String[] args) {
Node head1 = new Node(1);
Node node1 = new Node(3);
Node node2 = new Node(4);
Node node3 = new Node(4);
Node node4 = new Node(6);
head1.next = node1;
node1.next = node2;
node2.next = node3;
node3.next = node4;
Node head2 = new Node(2);
Node node5 = new Node(3);
Node node6 = new Node(4);
Node node7 = new Node(8);
Node node8 = new Node(9);
head2.next = node5;
node5.next = node6;
node6.next = node7;
node7.next = node8;
printCommonPart(head1, head2);
}
private static void printCommonPart(Node head1, Node head2) {
System.out.print("common is"+" ");
if (head1 == null || head2 == null) {
return;
}
while (head1 != null && head2 != null) {
if (head1.value < head2.value) {
head1 = head1.next;
} else if (head1.value > head2.value) {
head2 = head2.next;
} else {
System.out.print(head1.value + " ");
head1 = head1.next;
head2 = head2.next;
}
}
}
}
测试结果,亲测可用:
common is 3 4