输入: 2 次数n
4 每次m个操作,且每次队列置空
PUSH 1 第i次操作
PUSH 2
PUSH 3
TOP
5
SIZE
PUSH 2
TOP
POP
TOP
输出: 1
0
2
-1
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = Integer.parseInt(sc.nextLine());
Queue<Integer> queue = new LinkedList<>();
for (int i = 0; i < n; i++) {
int m = Integer.parseInt(sc.nextLine());
queue.clear();
for (int j = 0; j < m; j++) {
String[] ss = sc.nextLine().split(" ");
if(ss[0].equals("POP")){
if(queue.isEmpty()){
System.out.println(-1);
}
}
else if(ss[0].equals("TOP")){
System.out.println(queue.isEmpty()?-1:queue.peek());
}
else if(ss[0].equals("SIZE")){
System.out.println(queue.size());
}
else if(ss[0].equals("PUSH")){
queue.offer(Integer.valueOf(ss[1]));
}
else if(ss[0].equals("CLEAR")){
queue.clear();
}
}
}
}
}
经典的分治算求平面中的最近点对的变形,唯一的区别是需要记录点是属于哪个阵营中。
先将平面中的点按x坐标值排序,找到中间点mid,递归的在左右两侧找距离最小的点对距离min,再按照y坐标值排序,在中间点mid左右不超过min的点,对于每个点只需与它之后的六个点进行比较,找到中间区域的最小值tempmin,与min相比较得到min的最终值
时间复杂度为O(nlogn),空间复杂度O(n)
import java.util.*;
public class Main{
static class Node{
double x,y;
int f;
}
public static double cal(Node x,Node y){
if(x.f == y.f){
return Double.MAX_VALUE;
}
return Math.sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y));
}
public static double mergeSort(Node[] nodes,int left,int right){
double min = Double.MAX_VALUE;
if(right-left <= 0){
return min;
}
if(right-left == 1){
return cal(nodes[left],nodes[right]);
}
int mid = left+(right-left)/2;
double mina = mergeSort(nodes,left,mid);
double minb = mergeSort(nodes,mid+1,right);
min = mina > minb ? minb : mina;
merge(nodes,left,mid,right);
Node[] temps = new Node[right-left+1];
int num = 0;
for (int i = left; i <= right; i++) {
if(Math.abs(nodes[i].x-nodes[mid].x) <= min){
temps[num++] = nodes[i];
}
}
double tempmin;
for (int i = 0; i < num; i++) {
for (int j = i+1; j < num && j < i+7; j++) {
tempmin = cal(nodes[i],nodes[j]);
if(tempmin < min){
min = tempmin;
}
}
}
return min;
}
public static void merge(Node[] nodes,int left,int mid,int right){
Node[] temp = new Node[right-left+1];
int j = left;
int k = mid+1;
int t = 0;
while(j <= mid && k <= right){
if(nodes[j].y < nodes[k].y){
temp[t++] = nodes[j++];
}
else{
temp[t++] = nodes[k++];
}
}
while(j <= mid){
temp[t++] = nodes[j++];
}
while(k <= right){
temp[t++] = nodes[k++];
}
t = 0;
while(left <= right){
nodes[left++] = temp[t++];
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = Integer.parseInt(sc.nextLine());
String[] ss = new String[2];
for (int i = 0; i < n; i++) {
int m = Integer.parseInt(sc.nextLine());
Node[] nodes = new Node[2*m];
for (int j = 0; j < m; j++) {
ss = sc.nextLine().split(" ");
Node node = new Node();
node.x = Double.valueOf(ss[0]);
node.y = Double.valueOf(ss[1]);
node.f = 0;
nodes[j] = node;
}
for (int j = m; j < 2*m; j++) {
ss = sc.nextLine().split(" ");
Node node = new Node();
node.x = Double.valueOf(ss[0]);
node.y = Double.valueOf(ss[1]);
node.f = 1;
nodes[j] = node;
}
Arrays.sort(nodes,(v1,v2)-> (int) (v1.x-v2.x));
System.out.println(String.format("%.3f",mergeSort(nodes,0,2*m-1)));
}
}
}
(1)用两个栈模拟队列,一个栈模拟入队列,一个栈模拟出队列;push()的时间复杂度为O(1),pop()的摊分时间复杂度为O(1),这是最巧妙的一种方法
(2)若存在不合法情况比如队列为空时进行pop()、peek()操作时,要进行判空;定义一个全局变量size,只有size != 0时,才进行pop()、peek()操作
(3)peek()操作的巧妙方法在于,在push()时,记录front值;如果stack2不为空,就return stack2.pop(),否则的话return front
(4)四个操作的时间复杂度都为O(1)
import java.util.*;
public class Main{
Stack<Integer> stack1;
Stack<Integer> stack2;
int size = 0;
int front = 0;
public Main() {
stack1 = new Stack<>();
stack2 = new Stack<>();
}
public void push(int x) {
if(stack1.empty()){
front = x;
}
stack1.push(x);
size++;
}
public int pop() {
if(size == 0){
return -1;
}
if(stack2.empty()){
while(!stack1.empty()){
stack2.push(stack1.pop());
}
}
size--;
return stack2.pop();
}
public int peek() {
if(!stack2.empty()){
return stack2.peek();
}
return front;
}
public boolean empty() {
return size==0?true:false;
}
}
输入 : 4 次数n
10 1 结点值 层数i
10 2
10 3
10 4
输出: 1 第i层祖先
2
5
-1
(1)具有n个结点的完全二叉树,树的高度为log(n)+1,其中log(n)为向下取整;Java中向上取整的API是Math.ceil(double a),向下取整的API是Math.floor(double a),此题可直接用Math.getExponent()+1获得树的高度,因为Math.getExponent()是无偏指数且向下取整
(2)x的k层祖先可由x/2获得,循环的次数为x所在层数减去k
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = Integer.parseInt(sc.nextLine());
for (int j = 0; j < n; j++) {
String[] ss = sc.nextLine().split(" ");
int p = Integer.valueOf(ss[0]);
int q = Integer.valueOf(ss[1]);
if((Math.getExponent(p)+1) > q){
int sum = Math.getExponent(p)+1-q;
while(sum > 0){
p = p/2;
sum--;
}
System.out.println(p);
}
else{
System.out.println(-1);
}
}
}
}