栈、队列、链表

解密QQ号——队列

问题描述

新学期开始了,小哈是小哼的新同,小哼向小哈询问QQ号,小哈当然不会直接告诉小哼。所以小哈给了小哼一串加密过的数字,同时小哈也告诉了小哼解密规则。规则是这样的:首先将第1个数删除,紧接着将第2个数放到这串数的末尾,再将第3个数删除并将第4个数再放到这串数的末尾,再将第5个数删除……直到剩下最后一个数,将最后一个数也删除。按照刚才删除的顺序,把这些删除的数连在一起就是小哈的QQ啦。现在你来帮帮小哼吧。小哈给小哼加密过的一串数是“6 3 1 7 5 8 9 2 4”。解密后小哈的QQ号应该是“6 1 5 9 4 7 2 8 3”。

输入格式:

只有2行
第1行有一个整数n (1<=n<=100000)
第2行有n个整数为加密过的QQ号,每个整数之间用空格隔开。每个整数在1~9之间。

输出格式:

只有一行,输出解密后的QQ号。

限制:

每个测试点1秒
50%的数据1<=n<=10000
100%的数据1<=n<=100000

样例 1 :

输入:
9
6 3 1 7 5 8 9 2 4
输出:
6 1 5 9 4 7 2 8 3
package com.qianwei.chapter2;

import java.util.Arrays;

public class QueueTest1 {

	public static void main(String[] args) {
		int[] a = {6,3,1,7,5,8,9,2,4};
		int[] q = Arrays.copyOf(a, 100);
		int head = 0;
		int tail = 9;
		while (head < tail) {
			System.out.print(q[head]+" ");
			head++;
			q[tail] = q[head];
			tail++;
			head++;
		}
	}
}

 

package com.qianwei.chapter2;

import java.util.Scanner;

class Queue {
	int[] data = new int[100];
	int head;
	int tail;
}

public class QueueTest2 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		Queue q = new Queue();
		q.head = 0;
		q.tail = 0;
		for (int i=0;i<9;i++) {
			q.data[q.tail] = sc.nextInt();
			q.tail++;
		}
		while (q.head < q.tail) {
			System.out.print(q.data[q.head]+" ");
			q.head++;
			q.data[q.tail] = q.data[q.head];
			q.tail++;
			q.head++;
		}
		sc.close();
	}
}

 

这题用Java中自带的类库写起来非常方便,如下所示 

package com.qianwei.chapter2;

import java.util.Deque;
import java.util.LinkedList;
import java.util.Scanner;

public class QueueTest3 {
  
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		Deque<Integer> q = new LinkedList<Integer>();
		for (int i=0;i<9;i++)
			q.offer(sc.nextInt());
		while (!q.isEmpty()) {
			System.out.print(q.poll()+" ");
			Integer t = q.poll();
			if (q.isEmpty()) {			//如果此时队列为空,则跳出循环
				System.out.print(t);
				break;
			}
			q.offer(t);
		}
		sc.close();
	}
}

 

解密回文——栈

问题描述

“xyzyx”是一个回文字符串,所谓回文字符串就是指正读反读均相同的字符序列,如“席主席”、“记书记”、“aha”和“ahaha”均是回文,但“ahah”不是回文。输入一行字符(仅包含小写英文字母a~z)请判断这行字符串是否为回文。

输入格式:

只有一行,仅包含小写英文字母a~z的字符串,长度小于等于100。

输出格式:

只有一行,如果是回文请输出YES,不是回文则输出NO,请注意大小写。

样例 1 :

输入:
ahah
输出:
NO

样例 2 :

输入:
ahaha
输出:
YES
package com.qianwei.chapter2;

import java.util.Scanner;

public class StackTest1 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		char[] a = new char[100];
		char[] s = new char[100];
		a = sc.next().toCharArray();
		int len = a.length;
		int mid = len/2-1;
		int top = 0;
		int next;
		for (int i=0;i<=mid;i++)
			s[++top] = a[i];
		if (len%2 == 0) 
			next = mid+1;
		else
			next = mid+2;
		for (int i=next;i<len;i++) {
			if (a[i] != s[top])
				break;
			top--;
		}
		if (top == 0)
			System.out.println("Yes");
		else
			System.out.println("No");
		
		sc.close();
	}
}

 

 这题同样用Java中自带的类库写起来非常方便,如下所示 

package com.qianwei.chapter2;

import java.util.Deque;
import java.util.LinkedList;
import java.util.Scanner;

public class StackTest2 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String s = sc.next();
		int len = s.length();
		int mid = len/2-1;
		Deque<Character> stack = new LinkedList<Character>();
		for (int i=0;i<=mid;i++)
			stack.push(s.charAt(i));
		int next;
		if (len%2 == 0) 
			next = mid+1;
		else
			next = mid+2;
		for (int i=next;i<len;i++) {
			if (s.charAt(i) != stack.pop())
				break;
		}
		if (stack.isEmpty())
			System.out.println("Yes");
		else
			System.out.println("No");
		sc.close();
	}	
}

 

 这题如果巧妙地使用StringBuffer自带的reverse()方法更简单

package com.qianwei.chapter2;

import java.util.Scanner;

public class StackTest3 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String s = sc.next();
		String t = new StringBuffer(s).reverse().toString();
		if (s.equals(t))
			System.out.println("Yes");
		else
			System.out.println("No");
		sc.close();
	}
}

 

问题描述

在编程当中我们只会用到三种括号:圆括号(),方括号[]和花括号{},编译器在编译的时候会检查括号是否正确匹配。例如{[()]}、{()[]{}}都是合法的匹配。但是([)]则是不合法的匹配。请编写一个程序来判断输入的括号序列是否合法。

输入格式:

只有一行,为( ) [ ] { }组成的序列,长度不超过100

输出格式:

只有一行,如果是合法匹配则输出YES,不合法则输出NO,请注意大小写

限制:

每个测试点1秒

样例 1 :

输入:
{([()]{})}
输出:
YES
package com.qianwei.chapter2;

import java.util.Deque;
import java.util.LinkedList;
import java.util.Scanner;

public class StackTest4 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String s = sc.next();
		Deque<Character> stack = new LinkedList<Character>();
		if (s.charAt(0)==')' || s.charAt(0)==']' || s.charAt(0)=='}')
			System.out.println("No");
		stack.push(s.charAt(0));
		for (int i=1;i<s.length();i++) {
			if (stack.peek()=='(' && s.charAt(i)==')')
				stack.pop();
			else if (stack.peek()=='[' && s.charAt(i)==']')
				stack.pop();
			else if (stack.peek()=='{' && s.charAt(i)=='}') 
				stack.pop();
			else
				stack.push(s.charAt(i));
		}
		if (stack.isEmpty())
			System.out.println("Yes");
		else
			System.out.println("No");
		sc.close();
	}
}

 

纸牌游戏——小猫钓鱼

问题描述

星期天小哼和小哈约在一起玩桌游,他们正在玩一个非常古怪的扑克游戏——“小猫钓鱼”。游戏的规则是这样的:将一副扑克牌平均分成两份,每人拿一份。小哼先拿出手中的第一张扑克牌放在桌上,然后小哈也拿出手中的第一张扑克牌,并放在小哼刚打出的扑克牌的上面,就像这样两人交替出牌。出牌时,如果某人打出的牌与桌上某张牌的牌面相同,即可将两张相同的牌及其中间所夹的牌全部取走,并依次放到自己手中牌的末尾。当任意一人手中的牌全部出完时,游戏结束,对手获胜。
           假如游戏开始时,小哼手中有 6 张牌,顺序为 2 4 1 2 5 6,小哈手中也有 6 张牌,顺序为 3 1 3 5 6 4,最终谁会获胜呢?现在你可以拿出纸牌来试一试。接下来请你写一个程序来自动判断谁将获胜。这里我们做一个约定,小哼和小哈手中牌的牌面只有 1~9。

package com.qianwei.chapter2;

import java.util.Scanner;

class QueueFish {
	int[] data = new int[1000];
	int head;
	int tail;
}

//指向栈底时,top==1;
class Stack {
	int[] data = new int[10];
	int top;
}

public class KittenFishing1 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		QueueFish q1 = new QueueFish();
		QueueFish q2 = new QueueFish();
		Stack s = new Stack();
		int[] book = new int[10];
		int t;
		
		q1.head = 0;
		q1.tail = 0;
		q2.head = 0;
		q2.tail = 0;
		
		s.top = 0;
		
		for (int i=0;i<6;i++) 
			q1.data[q1.tail++] = sc.nextInt();
		for (int i=0;i<6;i++) 
			q2.data[q2.tail++] = sc.nextInt();
		while (q1.head<q1.tail && q2.head<q2.tail) {
			t = q1.data[q1.head];
			System.out.println(t);
			if (book[t] == 0) {
				q1.head++;
				s.data[++s.top] = t;
				book[t] = 1;
			}else {
				q1.head++;
				q1.data[q1.tail++] = t;
				while (s.data[s.top] != t) {
					book[s.data[s.top]] = 0;
					q1.data[q1.tail++] = s.data[s.top--];
				}
				book[s.data[s.top]] = 0;
				q1.data[q1.tail++] = s.data[s.top--];
			}
			if (q1.head == q1.tail) break;
			
			t = q2.data[q2.head];
			System.out.println(t);
			if (book[t] == 0) {
				q2.head++;
				s.data[++s.top] = t;
				book[t] = 1;
			}else {
				q2.head++;
				q2.data[q2.tail++] = t;
				while (s.data[s.top] != t) {
					book[s.data[s.top]] = 0;
					q2.data[q2.tail++] = s.data[s.top--];
				}
				book[s.data[s.top]] = 0;
				q2.data[q2.tail++] = s.data[s.top--];
			}
		}
		
		if (q2.head == q2.tail) {
			System.out.println("小哼win");
			System.out.println("小哼当前手中的牌是:");
			for (int i=q1.head;i<q1.tail;i++)
				System.out.print(q1.data[i]+" ");
			if (s.top>0) {
				System.out.println("\n桌子上的牌是:");
				for (int i=0;i<s.top;i++)	//输出桌子上的牌不是按照出栈的顺序,而是相反的顺序输出
					System.out.print(s.data[i+1]+" ");
			}else 
				System.out.println("桌子上已经没有牌了");
		}else {
			System.out.println("小哈win");
			System.out.println("小哈当前手中的牌是:");
			for (int i=q2.head;i<q2.tail;i++)
				System.out.print(q2.data[i]+" ");
			if (s.top>0) {
				System.out.println("\n桌子上的牌是:");
				for (int i=0;i<s.top;i++)
					System.out.print(s.data[i+1]+" ");
			}else 
				System.out.println("桌子上已经没有牌了");
		}
		sc.close();
	}
}

 

 这题同样用Java中自带的类库写起来非常方便,如下所示  

package com.qianwei.chapter2;

import java.util.Deque;
import java.util.LinkedList;
import java.util.Scanner;

public class KittenFishing2 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		Deque<Integer> q1 = new LinkedList<Integer>();
		Deque<Integer> q2 = new LinkedList<Integer>();
		Deque<Integer> stack = new LinkedList<Integer>();
		int[] book = new int[10];
		
		for (int i=0;i<6;i++) 
			q1.offer(sc.nextInt());
		for (int i=0;i<6;i++) 
			q2.offer(sc.nextInt());
		while (!q1.isEmpty() && !q2.isEmpty()) {
			int t = q1.peek();
			if (book[t] == 0) {
				q1.poll();
				stack.push(t);
				book[t] = 1;
			}else {
				q1.offer(q1.poll());
				while (stack.peek() != t) {
					book[stack.peek()] = 0;
					q1.offer(stack.pop());
				}
				book[stack.peek()] = 0;
				q1.offer(stack.pop());
			}
			if (q1.isEmpty()) break;
			
			t = q2.peek();
			if (book[t] == 0) {
				q2.poll();
				stack.push(t);
				book[t] = 1;
			}else {
				q2.offer(q2.poll());
				while (stack.peek() != t) {
					book[stack.peek()] = 0;
					q2.offer(stack.pop());
				}
				book[stack.peek()] = 0;
				q2.offer(stack.pop());
			}
		}
		
		if (q2.isEmpty()) {
			System.out.println("小哼win");
			System.out.println("小哼当前手中的牌是:");
			//一开始这样写运行结果老是有问题,后来发现原来是q1.size()不是固定不变的,
			//随着q1.poll()的执行,q1.size()的值也在变化,所以导致最终输出赢赢的人手中的牌不正确
//			for (int i=0;i<q1.size();i++)
//				System.out.print(q1.poll()+" ");
			//改成这样就不会出现上面的那种情况了
			while (!q1.isEmpty())
				System.out.print(q1.poll()+" ");
			if (!stack.isEmpty()) {
				System.out.println("\n桌子上的牌是");
				//这里也同样,stack.size()的值是随着stack.removeLast()的执行而变化
//				for (int j=0;j<stack.size();j++)
//					System.out.print(stack.removeLast()+" ");
				while (!stack.isEmpty())	//输出桌子上的牌不是按照出栈的顺序,而是相反的顺序输出
					System.out.print(stack.removeLast()+" ");
			}else 
				System.out.println("桌子上已经没有牌了");
		}else {
			System.out.println("小哈win");
			System.out.println("小哈当前手中的牌是:");
//			for (int i=0;i<q1.size();i++)
//				System.out.print(q1.poll()+" ");
			while (!q2.isEmpty())
				System.out.print(q2.poll()+" ");
			if (!stack.isEmpty()) {
				System.out.println("\n桌子上的牌是");
//				for (int j=0;j<stack.size();j++)
//					System.out.print(stack.removeLast()+" ");
				while (!stack.isEmpty())
					System.out.print(stack.removeLast()+" ");
			}else 
				System.out.println("桌子上已经没有牌了");
		}
		sc.close();
	}
}

 

链表

问题描述

用链表存储n个数,这n个数按从小到大的顺序输入。书上的C语言代码辣么辣么长,还有一堆指针指来指去,看着就烦,看我用Java几行代码就搞定。

package com.qianwei.chapter2;

import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

public class LinkedListTest1 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		List<Integer> list = new LinkedList<Integer>();
		for (int i=0;i<n;i++)
			list.add(sc.nextInt());
		for (int j=0;j<n;j++)
			System.out.print(list.get(j)+" ");
		sc.close();
	}
}

 

 实现在链表中间插入一个元素

package com.qianwei.chapter2;

import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

public class LinkedListTest2 {
	
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		List<Integer> list = new LinkedList<Integer>();
		for (int i=0;i<n;i++)
			list.add(sc.nextInt());
		int insert = sc.nextInt();
		int index = 0;
		for (int j=0;j<n;j++) {
			if (list.get(j) > insert) {
				index = list.lastIndexOf(list.get(j));
				break;
			}
		}
		list.add(index, insert);
		for (int k=0;k<n;k++)
			System.out.print(list.get(k)+" ");
		sc.close();
	}
}

 

模拟链表

问题描述

链表中的每一个结点只有两个部分。我们可以用一个数组 data 来存储每序列中的每一个数。那每一个数右边的数是谁,这一点该怎么解决呢?上一节中是使用指针来解决的,这里我们只需再用一个数组right来存放序列中每一个数右边的数是谁就可以了。

package com.qianwei.chapter2;

import java.util.Scanner;

//有bug 如果插入的元素大于链表中所有的元素会出现bug,导致无法插入元素
public class LinkedListDemo {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int[] data = new int[100];
		int[] right = new int[100];
		int n = sc.nextInt();
		for (int i=0;i<n;i++)
			data[i] = sc.nextInt();
		for (int i=0;i<n;i++) {
			if (i != n-1)
				right[i] = i+1;
			else
				right[i] = 0;
		}
		
		data[n] = sc.nextInt();
		int t = 0;
		while (true) {
			if (data[right[t]]>data[n]) {
				right[n] = right[t];
				right[t] = n;
				break;
			}
			t = right[t];
		}
		t = 0;
		while (true) {
			System.out.print(data[t]+" ");
			t = right[t];
			if (t == 0)
				break;
		}
		sc.close();
	}
}

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值