数据结构和算法的笔试题
- 排序:1、全排列:给出五个数字12345的所有排列。
public static void perm(int[] list) {
perm(list,0);
}
private static void perm(int[] list, int k) {
if (k == list.length) {
for (int i = 0; i < list.length; i++) {
System.out.print(list[i]);
}
System.out.println();
}else{
for (int i = k; i < list.length; i++) {
swap(list, k, i);
perm(list, k + 1);
swap(list, k, i);
}
}
}
private static void swap(int[] list, int pos1, int pos2) {
int temp = list[pos1];
list[pos1] = list[pos2];
list[pos2] = temp;
}
public static void main(String[] args) {
int[] x = {1, 2};
perm(x);
}
- 排序:2、输入三个整数x,y,z,请把这三个数由小到大输出
import java.util.Arrays;
import java.util.Scanner;
public static void main(String[] args) {
System.out.println("请输入三位整数:");
Scanner in = new Scanner(System.in);
int[] arr = new int[3];
for (int i = 0;i<3;i++){
arr[i] = in.nextInt();
}
Arrays.sort(arr);
for (int i=0;i<arr.length;i++){
System.out.println(arr[i] + "");
}
}
- 字符串:
3、描述:给定一个非空字符串s和一个包含非空单词列表的字典wordDict,判断s是否可以被空格拆分为一个或者多个字典中出现的单词。
说明:
1)拆分时可以重复使用字典中的单词。
2)你可以建设字典中没有重复的单词。
public static void main(String[] args) {
String source = "xinhuahuaxinhua";
String[] wordDict = {"xinhua","hua"};
System.out.println(execute(source,0,wordDict));
}
private static boolean execute(String source,int i,String[] wordDict) {
//如果已到结尾,则返回
if (i >= source.length()) {
return true;
}
boolean v = false;
for (String dict : wordDict) {
int l = dict.length();
if (i + l <= source.length()) {
String current = source.substring(i, i + l);
if (!dict.equals(current)) {
continue;
}
//如果当前字典匹配,则比较剩余的子字符串是否仍然匹配
boolean x = execute(source, i + l, wordDict);
//只要有一个匹配,则认为成功
if (x) {
return true;
}
}
}
return v;
}
- 算法:
4、给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
import java.util.HashSet;
import java.util.Set;
public static void main(String[] args) {
String source = "abcabcbb";
System.out.println(execute(source));
}
public static int execute(String source) {
Set<Character> container = new HashSet<>();
int s = 0;//辅助,无重复子串的开始index
int e = 1;//辅助,无重复子串的结束index + 1,便于计算长度
int max = e - s;
for (int i = 0; i < source.length(); i++) {
char value = source.charAt(i);
//如果发现重复字符,则清空set,计算max,重新开始
if (container.contains(value)) {
max = Math.max(max,e -s);
System.out.println(source.substring(s,e));
s = i;
container.clear();
}
container.add(value);
e = i + 1;
}
return max;
}
- 递归算法:
5、利用递归算法求5!
public static void main(String[] args) {
int n= 5;
rec fr = new rec();
System.out.println(n+"! ="+fr.rec(n));
}
static class rec{
public long rec(int n){
long value =0;
if (n==1){
value=1;
}else {
value = n * rec(n-1);
}
return value;
}
}
- 链表:
6、描述:给定一个链表和一个特定值x,对链表进行分隔,使得所有小于x节点的都在 大于或者等于x的节点之前。
示例:
输入: head = 1->4->3->2->5->2, x = 3
输出: 1->2->2->4->3->5
提示:结果并非排序的,只需要 小于3的节点都在大于或者等于三的之后即可。
public static void main(String[] args) {
ListNode root = new ListNode(0);//0为标记值
ListNode source = root;
root = (root.next = new ListNode(1));
root = (root.next = new ListNode(4));
root = (root.next = new ListNode(3));
root = (root.next = new ListNode(2));
root = (root.next = new ListNode(5));
root = (root.next = new ListNode(2));
//root.next = new ListNode(3);
ListNode result = execute(source.next,3);
System.out.println(result);
}
private static ListNode execute(ListNode head,int target) {
//首先创建两个链表,分表保存大于、小于target的节点
ListNode left = new ListNode(0);//比target小的链表
ListNode right = new ListNode(0);//比target大的链表
ListNode pl = left;
ListNode pr = right;//两个指针
while (head != null) {
if (head.value < target) {
//添加到左边链表
pl.next = head;
pl = pl.next;//head.next
} else {
pr.next = head;
pr = pr.next;
}
head = head.next;//向前推进
}
pr.next = null;//尾部
pl.next = right.next;//左端的尾部与右端的头,拼接
return left.next;
}
public static class ListNode {
int value = 0;
ListNode next = null;
ListNode(int value) {
this.value = value;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(value);
ListNode t = next;
while (t != null) {
sb.append(t.value);
t = t.next;
}
return sb.toString();
}
}
- 链表:
7、俩数相加
描述:使用两个非空的链表表示两个非负整数,链表为单向链表,它们各自的位数是按照逆序的方式存储,链表中每个节点只存储一位数字。(链表节点与整数字面值输入顺序一)
返回一个新的链表,表示两个整数之和。(逆序)
示例:
输入:
342:2 -> 4 -> 3
465:5 -> 6 -> 4
输出和:
807: 7 -> 0 -> 8
public static void main(String[] args) {
//构建部分
ListNode l1 = new ListNode(0);
ListNode ll1 = l1;
ll1 = (ll1.next = new ListNode(2));
ll1 = (ll1.next = new ListNode(4));
ll1.next = new ListNode(3);
ListNode l2 = new ListNode(0);
ListNode ll2 = l2;
ll2 = (ll2.next = new ListNode(5));
ll2 = (ll2.next = new ListNode(6));
ll2.next = new ListNode(4);
ListNode result = execute(l1,l2);
System.out.println("result:");
System.out.println(result.next);
}
public static ListNode execute(ListNode l1,ListNode l2) {
ListNode r = new ListNode(0);
ListNode p = l1.next;
ListNode q = l2.next;
ListNode result = r;//指向head
int c = 0;
while (true) {
int x = p == null ? 0 : p.value;
int y = q == null ? 0 : q.value;
int t = x + y + c;
if (t > 9) {
c = 1;
r.next = new ListNode(t % 10);
} else {
c = 0;
r.next = new ListNode(t);
}
p = p.next;
q = q.next;
r = r.next;
if (p == null && q == null) {
break;
}
}
return result;
}
public static class ListNode {
int value = 0;
ListNode next = null;
ListNode(int value) {
this.value = value;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(value);
ListNode t = next;
while (t != null) {
sb.append(t.value);
t = t.next;
}
return sb.toString();
}
}
- 完全平方数:
8、描述:给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
示例 1:
输入: n = 12
输出: 3
解释: 12 = 4 + 4 + 4.
public static void main(String[] args) {
System.out.println(execute(12));
}
/**
* 动态规划
* @param n
* @return
*/
private static int execute(int n) {
int result = n;//最大为n个1平方
int i = 2;//每个余数都从2开始计算
while (true) {
//依次取平方
int value = i * i;
//超限则返回
if (value > n) {
break;
}
//t为i平方的个数,n = t * (i * i) + ?
int t = n / (value);
//余数,继续按照此规则
int next = n % (value);
result = Math.min(result, t + execute(next));
i++;
}
return result;
}
- 运算符算法:
9、利用条件运算符的嵌套来完成此题:学习成绩> =90分的同学用A表示,60-89分之间的用B表示,60分以下的用C表示。
public static void main(String[] args){
String str="";
str= JOptionPane.showInputDialog("请输入N的值(输入exit退出):");
int N;
N=0;
try{
N=Integer.parseInt(str);
}
catch(NumberFormatException e){
e.printStackTrace();
}
str=(N>90?"A":(N>60?"B":"C"));
System.out.println(str);
}
- 数组:
10、描述:给定两个有序数组num1和num2,将num2合并到num1中,是的num1成为一个有序数据。
说明:1)初始化num1和num2的元素数量分表为m和n。
2)我们假设nums1有足够的空间(m + n <= num1.length)来保存num2的元素。
示例:
输入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3
输出: [1,2,2,3,5,6]
public static void main(String[] args) {
int[] source1 = {1,2,3,0,0,0};
int[] source2 = {2,5,6};
execute(source1,source2,3,3);
System.out.println(source1);
}
private static void execute(int[] source1,int[] source2,int m,int n) {
int l1 = m - 1;//较长
int l2 = n - 1;
int x = m + n - 1;
while (l1 >= 0 && l2 >= 0) {
int i = source1[l1];
int j = source2[l2];
if (j >= i) {
source1[x] = j;
l2--;
} else {
source1[x] = i;
//如果是source1的元素较大,那么我们应该把元位置置换为0,即空位置。
source1[l1] = 0;
l1--;
}
x--;
}
}