1.定义一个数组,使用选择排序对数组进行排序
1.1选择排序
public class Hello1 {
public static void main(String[] args) {
int arr [] ={1,90,56,123,9,8,6,7,2,8,1};
for (int i = 0; i <arr.length-1 ; i++) {
int minIndex=i;//最小下标默认值
//1.从i到len-1这个范围中找最小值下标
for (int j = i; j <=arr.length-1 ; j++) {
if (arr[j]<arr[minIndex]){
minIndex=j;
}
}
//2.交换元素
int t=arr[i];
arr[i]=arr[minIndex];
arr[minIndex]=t;
}
//输出数组
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
}
}
1.2 快速排序
import java.util.Arrays;
public class TestBubble {
public static void main(String[] args) {
fun3();
}
private static void fun3() {
int arr []={8,5,0,1,4};
int[] arr2 = quickSort(arr, 0, arr.length - 1);
System.out.println(Arrays.toString(arr2));
}
// 快 速
private static int [] quickSort(int arr[],int l,int r) {
int X=arr[l];
int i=l,j=r;
while (i<j){
//从右向左,找出比X小的数的下标 j
while (i<j &&arr[j]>X){
j--;
}
//从左向右,找出比X大的数的下标
while (i<j &&arr[i]<X){
i++;
}
if(arr[i]==arr[j]&&i<j){
i++;
}else {
int t=arr[i];
arr[i]=arr[j];
arr[j]=t;
}
}
if(i-1>l){
arr=quickSort(arr,l,i-1);
}
if(j+1<r){
arr=quickSort(arr,j+1,r);
}
return arr;
}
}
1.3冒泡排序
public class Hello1 {
public static void main(String[] args) {
int arr[]={9,4,5,6,8,1,40};
for (int i = 1; i <=arr.length-1; i++) {
for (int j = 0; j <=arr.length-i-1; j++) {
if (arr[j]>arr[j+1]){
int t=arr[j];
arr[j]=arr[j+1];
arr[j+1]=t;
}
}
}
//输出数组
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
}
}
2.定义一个字符串,统计其中字符的个数
static void test_4() {
/*
* 统计字符串中每个字符的个数
* 例如 字符串 为 aabb112, 输出为a()b()1()2(),2()
*
* a="ssddsdfsadfs";
* 获取第0个字符,遍历和其余字符串比较 相等 加1
* b = a(2)
* a ="bb";
* 获取第0个字符,遍历和其余字符串比较 相等 加1
* b = a(2)b(2);
* a=""
*/
String a= "j aakethehoworkfang ,,, ";
String b = "";
while(a.length() > 0) {
//统计字符个数
int sum =1;
//获取需要被统计个数的字符
char ch = a.charAt(0);
for(int i = 1; i<a.length();i++) {
char c =a.charAt(i);
if(ch ==c) {
sum ++;
}
}
//ch统计完成
b = b + ch + "(" + sum +")";
//将统计过的替换掉
a = a.replace(ch+"","");
}
System.out.println(b);
}
3.现在有两个文件a.txt和b.txt,其中有一些单词,单词都是以空格隔开;要求:将a和b中的所有单词交替合并到c.txt中
4.定义一个方法,可以对目录进行拷贝
// 3.定义一个方法,可以拷贝文件夹
/**
* 拷贝文件夹的方法
* @param srcPath 源文件夹的路径
* @param desPath 目标文件夹的上一级路径
* @return 如果拷贝成功返回true,反之返回false
* @throws IOException
*/
static boolean copyFile(String srcPath, String desPath) throws IOException {
// 源文件夹
File srcFile = new File(srcPath);
if(!srcFile.exists() || !srcFile.isDirectory()) {
// 说明源文件夹为空或者文件夹不存在
throw new FileNotFoundException("源文件夹不存在或者源文件夹不是文件夹!");
}
// 得到源文件夹的名字
String name = srcFile.getName();
// 目标文件夹的上一级目标路径
File desFile = new File(desPath);
if(!desFile.exists() || !desFile.isDirectory()) {
throw new FileNotFoundException("目标文件夹父路径不存在或者不是一个文件夹!");
}
// 目标文件夹
String item = desPath;
desPath = item + "\\" + name;
desFile = new File(desPath);
desFile.mkdir();
if(desFile.getPath().equals(srcFile.getPath())) {
throw new FileNotFoundException("在同一个目标文件夹下,不能拷贝!");
}
// 说明可以拷贝了 逐个拷贝里面的文件
File[] subFiles = srcFile.listFiles();
String temp = srcPath;
//System.out.println("temp = " + temp);
for(File sub : subFiles) {
if(sub.isFile()) {
// 说明sub是文件,直接拷贝文件
srcPath = temp + "\\" + sub.getName();
//System.out.println("文件srcPath =" + srcPath);
copy(srcPath, desPath);
}else {
srcPath = temp + "\\" + sub.getName();
//System.out.println("srcPath = " + srcPath);
//System.out.println("desPath = " + desPath);
copyFile(srcPath, desPath);
}
}
return true;
}
5.现有一个双向链表,判断该链表是否是回文
1.方法1:将链表元素都赋值到数组中,然后可以从数组两端向中间对比。主要是在while循环中pre.next = prepre;和prepre = pre;实现了一边遍历一遍将访问过的链表给反转了,所以理解起来有些难度,
快慢指针法
public boolean isPalindrome(ListNode head) {
if(head == null || head.next == null) {
return true;
}
ListNode slow = head, fast = head;
ListNode pre = head, prepre = null;
while(fast != null && fast.next != null) {
pre = slow;
slow = slow.next;
fast = fast.next.next;
//将前半部分链表反转
pre.next = prepre;
prepre = pre;
}
if(fast != null) {
slow = slow.next;
}
while(pre != null && slow != null) {
if(pre.val != slow.val) {
return false;
}
pre = pre.next;
slow = slow.next;
}
return true;
}
-
使用栈:全部压栈
public boolean isPalindrome(ListNode head) { ListNode temp = head; Stack<Integer> stack = new Stack(); //把链表节点的值存放到栈中 while (temp != null) { stack.push(temp.val); temp = temp.next; } //然后再出栈 while (head != null) { if (head.val != stack.pop()) { return false; } head = head.next; } return true; }
3.使用栈:部分压栈
改造上面的方法,先遍历第一遍,得到总长度。之后一遍历链表,一遍压栈。当到达链表长度一半的位置之后,就不再压栈,而是一边出栈,一遍遍历,一遍比较,只要有一个不相等,就不是回文链表。代码就是这样:
public boolean isPalindrome(ListNode head) {
if (head == null)
return true;
ListNode temp = head;
Stack<Integer> stack = new Stack();
//链表的长度
int len = 0;
//把链表节点的值存放到栈中
while (temp != null) {
stack.push(temp.val);
temp = temp.next;
len++;
}
//len长度除以2
len >>= 1;
//然后再出栈
while (len-- >= 0) {
if (head.val != stack.pop())
return false;
head = head.next;
}
return true;
}
6.一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶,求该青蛙跳上n级台阶总共有多少中跳法
解题思路🍖
若n为1级台阶:f(1) = 1 (只可能有一种跳法)
若n为2级台阶:f(2) = f(2 - 1) + f(2 - 2)(会有两个跳得方式,一次1阶或者一次2阶)
若n为3级台阶:f(3) = f(3 - 1) + f(3 - 2) + f(3 - 3)(会有三种跳得方式,一次1阶、2阶、3阶)
……
……
若n为(n - 1)级台阶:
f(n-1) = f((n-1)-1) + f((n-1)-2) + … + f((n-1)-(n-2)) + f((n-1)-(n-1))
f(n-1) = f(0) + f(1)+f(2)+f(3) + … + f((n-1)-1)
f(n-1) = f(0) + f(1) + f(2) + f(3) + … + f(n-2)
若n为n级台阶:
f(n) = f(n-1) + f(n-2) + f(n-3) + … + f(n-(n-1)) + f(n-n)
f(n) = f(0) + f(1) + f(2) + f(3) + … + f(n-2) + f(n-1)
结合f(n-1)和f(n)的情况你会发现f(n) = f(n-1) + f(n-1),所以可得: f(n) = 2*f(n-1)。
7.有多个有序的list集合,将这多个集合合并为一个集合,和并之后的集合也要保证有序
在Java中,你可以使用优先队列(PriorityQueue)来合并多个有序列表,同时保持结果有序。以下是一个示例代码,演示如何合并多个有序列表:
```java
import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;
public class MergeSortedLists {
public static List<Integer> mergeSortedLists(List<List<Integer>> lists) {
List<Integer> result = new ArrayList<>();
PriorityQueue<Pair> minHeap = new PriorityQueue<>((a, b) -> a.value - b.value);
// 初始化优先队列,将每个列表的第一个元素加入队列
for (int i = 0; i < lists.size(); i++) {
if (!lists.get(i).isEmpty()) {
minHeap.offer(new Pair(i, 0, lists.get(i).get(0)));
}
}
while (!minHeap.isEmpty()) {
Pair pair = minHeap.poll();
int listIndex = pair.listIndex;
int elementIndex = pair.elementIndex;
// 添加当前最小元素到结果列表
result.add(pair.value);
// 移动到下一个元素
elementIndex++;
if (elementIndex < lists.get(listIndex).size()) {
minHeap.offer(new Pair(listIndex, elementIndex, lists.get(listIndex).get(elementIndex)));
}
}
return result;
}
static class Pair {
int listIndex;
int elementIndex;
int value;
Pair(int listIndex, int elementIndex, int value) {
this.listIndex = listIndex;
this.elementIndex = elementIndex;
this.value = value;
}
}
public static void main(String[] args) {
List<List<Integer>> lists = new ArrayList<>();
lists.add(List.of(1, 3, 5));
lists.add(List.of(2, 4, 6));
lists.add(List.of(0, 7, 8));
List<Integer> result = mergeSortedLists(lists);
System.out.println(result); // 输出 [0, 1, 2, 3, 4, 5, 6, 7, 8]
}
}
```
这段Java代码使用优先队列(最小堆)来维护多个列表的当前元素,并不断选择最小的元素添加到结果列表中。这种方法的时间复杂度为 O(NlogK),其中 N 是所有元素的总数,K 是列表的数量。它能够有效地合并多个有序列表并保持结果有序。
要将多个有序的列表合并成一个有序的列表,可以使用归并排序的思想。以下是一个示例的Java代码实现:
import java.util.ArrayList;
import java.util.List;
public class MergeSortedLists {
public static void main(String[] args) {
List<Integer> list1 = List.of(1, 3, 5, 7);
List<Integer> list2 = List.of(2, 4, 6, 8);
List<Integer> list3 = List.of(0, 9, 10);
List<Integer> mergedList = mergeSortedLists(list1, list2, list3);
System.out.println("Merged List: " + mergedList);
}
public static List<Integer> mergeSortedLists(List<Integer>... lists) {
List<Integer> mergedList = new ArrayList<>();
// Initialize pointers for each list
int[] pointers = new int[lists.length];
// Merge lists until all elements are processed
while (true) {
// Find the smallest element among the current pointers
int smallest = Integer.MAX_VALUE;
int smallestListIndex = -1;
for (int i = 0; i < lists.length; i++) {
List<Integer> list = lists[i];
int pointer = pointers[i];
if (pointer < list.size() && list.get(pointer) < smallest) {
smallest = list.get(pointer);
smallestListIndex = i;
}
}
// If all pointers have reached the end, break the loop
if (smallestListIndex == -1) {
break;
}
// Add the smallest element to the merged list
mergedList.add(smallest);
// Move the pointer of the list that contains the smallest element
pointers[smallestListIndex]++;
}
return mergedList;
}
}
在上述示例中,我们有三个有序列表 list1 、 list2 、 list3 。我们使用 mergeSortedLists 方法将这三个列表合并成一个有序的列表 mergedList 。最后,我们将合并后的列表打印到控制台上。 输出结果:
Merged List: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
注意:在示例中,我们假设输入的列表已经是有序的。如果输入的列表不是有序的,你可以在合并之前先对每个列表进行排序。
8.定义两个线程,交替打印奇偶数
场景一:线程A打印奇数,线程B打印偶数,线程A和线程B交替打印,使用对象监视器实现。线程A和线程B交替打印奇数和偶数,使用对象监视器实现,通俗来说:线程A或线程B只要有一者竞争锁成功,就打印++i,通知其他线程从等待集合中释放,然后自身线程加入等待集合并且释放锁即可。
public class OddEvenPrinter {
private final Object monitor = new Object();
private final int limit;
private volatile int count;
public OddEvenPrinter(int limit, int initCount) {
this.limit = limit;
this.count = initCount;
}
public void print() {
synchronized (monitor) {
while (count < limit) {
try {
System.out.println(String.format("线程[%s]打印数字:%d", Thread.currentThread().getName(), ++count));
monitor.notifyAll();
monitor.wait();
} catch (InterruptedException e) {
//ignore
}
}
}
}
public static void main(String[] args) throws Exception {
OddEvenPrinter printer = new OddEvenPrinter(10, 0);
Thread thread1 = new Thread(printer::print, "thread-1");
Thread thread2 = new Thread(printer::print, "thread-2");
thread1.start();
thread2.start();
Thread.sleep(Integer.MAX_VALUE);
}
}
场景二:线程A打印奇数,线程B打印偶数,线程A和线程B交替打印,使用JDK提供的并发类库实现。如果需要使用JUC中提供的并发类库,可以考虑和对象监视器功能接近的可重入锁ReentrantLock
public class OddEvenPrinterEx {
private final ReentrantLock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
private final int limit;
private volatile int count;
public OddEvenPrinterEx(int limit, int initCount) {
this.limit = limit;
this.count = initCount;
}
public void print() {
lock.lock();
try {
while (count < limit){
System.out.println(String.format("线程[%s]打印数字:%d", Thread.currentThread().getName(), ++count));
condition.signalAll();
try {
condition.await();
} catch (InterruptedException e) {
//ignore
}
}
} finally {
lock.unlock();
}
}
public static void main(String[] args) throws Exception {
OddEvenPrinterEx printer = new OddEvenPrinterEx(10, 0);
Thread thread1 = new Thread(printer::print, "thread-1");
Thread thread2 = new Thread(printer::print, "thread-2");
thread1.start();
thread2.start();
Thread.sleep(Integer.MAX_VALUE);
}
}