顺序查找
分治算法
回溯、分治、和动态规划算法可以规划为一类,都会涉及到递归。
动态规划是一类算法问题,
动态规划
递归求x的n次方
package Temp;
import java.util.Scanner;
/*
* @Author: jun
* @Date:2023/1/30 0:03
* @概述:
*/
public class niuke004 {
//求x的n次方
static int function01(int x, int n){
int result = 1;//把结果赋值为1是为了表示所有的数的0次方都是1
for (int i = 0; i < n; i++) {//循环n次中每次的result都是取了n-1次方的结果
result = result * x;
}
return result;//返回x的n次方
}
static int recursive(int x, int n){
if (n == 0){
return 1;
}
return x*recursive(x,n-1);
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
//使用普通的for循环计算x的n次方结果
System.out.println("使用普通的for循环计算x的n次方结果");
System.out.println("输入x的值:");
int x = scanner.nextInt();
System.out.println("输入n的值:");
int n = scanner.nextInt();
long start = System.nanoTime();
System.out.println("result="+function01(x,n));
long end = System.nanoTime();
System.out.println("时间消耗"+(end-start));
System.out.println("_________________");
//使用递归的算法解决该题
System.out.println("使用递归的算法解决该题");
long start02 = System.nanoTime();
System.out.println("recursive result="+recursive(x,n));
long end02 = System.nanoTime();
System.out.println("时间消耗"+(end02-start02));
}
}
有序数组的平方排列
package Temp;
/*
* @Author: jun
* @Date:2023/2/17 8:32
* @概述:
*/
public class niuke005 {
//有序数组的平方排列
static class solution{
public int[] sortSquares(int[] nums){
int right = nums.length-1;//定义右指针
int left = 0;//定义左指针
int[] result = new int[nums.length];//新建一个数组用于返回排序后结果,并且大小等于原需排列的数组
int index = result.length-1;//给新建的数组也定义一个指针,让它从最后一位开始移动,返回比较后的较大值
while(left<=right){//常规的双指针的条件就是左指针与右指针交错
//每次比较是用平方后的值来比较
if (nums[left]*nums[left] > nums[right]*nums[right]){
//将大的left添入新数组的右边,
result[index--] = nums[left]*nums[left];
++left;//将原数组比较的左指针右移,right不变
} else {
//相反的
result[index--] = nums[right]*nums[right];
--right;
}
}
return result;
}
}
public static void main(String[] args) {
int[] arr = {-1,2,3,5,8,17};
solution solution = new solution();
int[] ints = solution.sortSquares(arr);
for (int i:ints
) {
System.out.println(i);
}
}
}
前n项和的时间复杂度
package Temp;
/*
* @Author: jun
* @Date:2023/2/17 9:01
* @概述:
*/
public class temp006 {
//前n项和的时间复杂度
//1+2+3+···+100
static int solution01(int n){
int sum = 0;
while(n>0){
sum+=n;
n--;
}
return sum;
}
//设计时间复杂度为O(1)的算法
static int solution02(int n){
return n*(n+1)/2;
}
//解法三
public static void main(String[] args){
long stime = System.nanoTime();
System.out.println(solution01(100));
long etime = System.nanoTime();
long time01 = System.nanoTime();
System.out.println(solution02(100));
long time02 = System.nanoTime();
System.out.println(etime-stime);
System.out.println(time02-time01);
}
}
两个数组的交集
package Temp;
/*
* @Author: jun
* @Date:2023/2/17 13:24
* @概述:
*/
import java.util.HashSet;
/**
* 两个数组的交集
* 题意:给定两个数组,编写一个函数来计算它们的交集
*/
public class temp008 {
public static int[] intersection(int[] nums1,int[] nums2){
//首先判断这两个数组是否是空的,如果有一方是空的就直接放回一个空数组
if (nums1 == null || nums1.length == 0 || nums2 == null || nums2.length == 0){
return new int[0];
}
//新建两个hashset
HashSet<Object> set1 = new HashSet<>();
HashSet<Object> resSet = new HashSet<>();
//遍历数组set1
for (int i:nums1) {
set1.add(i);
}
//遍历数组2的过程中判断哈希表set1中是否存在该元素
for ( int i:nums2){
if (set1.contains(i)){
resSet.add(i);
}
}
return resSet.stream().mapToInt(x -> (int) x).toArray();
}
public static void main(String[] args) {
int[] arr1 = {1,2,3,4,5,5};
int[] arr2 = {1,5};
for (int i: intersection(arr1,arr2)
) {
System.out.println(i);
}
}
}
快乐数
package Temp;
/*
* @Author: jun
* @Date:2023/2/17 13:40
* @概述:
*/
import java.util.HashSet;
import java.util.Set;
/**
* 快乐数
* 编写一个算法来判断一个数是否是快乐数
* 快乐数的定义:对于一个正整数,
* 每一次将该数替换为它每一个位置上的数字的平方和,
* 然后重复这个过程直到这个数变为一,也可能是无限循环
* 但最终变不到一,如果可以变为一,那么这个数就是快乐数。
*/
public class temp009 {
//获取每位数
static int getNextNumber(int n){
int res = 0;//返回值
while(n>0){
int temp = n%10;//取得一位数
res += temp*temp;//每位数都要进行平方求其值
n = n / 10;//相当于末尾位取出
System.out.println(temp);
}
return res;
}
public static void main(String[] args) {
getNextNumber(113);
int n = 123;
Set<Integer> record = new HashSet<>();
while(n!=1&&!record.contains(n)){
record.add(n);
n = getNextNumber(n);
}
System.out.println(n);
}
}
两数之和
package Temp;
/*
* @Author: jun
* @Date:2023/2/17 16:15
* @概述:
*/
import java.util.HashMap;
/**
* 两数之和
*
*/
public class temp010 {
static int[] twoSum(int[] nums,int target){
int[] res = new int[2];//返回值为一个两个空间大小的数组
if (nums == null || nums.length == 0){
return res;
}
HashMap<Integer, Integer> map = new HashMap<>();//新建一个哈希表,键和值都是整型
for (int i = 0; i < nums.length; i++) {
int temp = target - nums[i];//遍历当前元素,并在map中寻找是否有匹配的数
if(map.containsKey(temp)){
res[1] = i;
res[0] = map.get(temp);
break;
}
map.put(nums[i],i);//每次循环都把遍历过的数放进map
}
return res;
}
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6};
int target = 10;
int[] ints = twoSum(arr, target);
for (int i :
ints) {
System.out.println(i);
}
}
}
四数相加
package Temp;
/*
* @Author: jun
* @Date:2023/2/17 16:47
* @概述:
*/
import java.util.HashMap;
import java.util.Map;
/**
* 四数相加
* 给定四个包含整数的数组列表A,B,C,D,计算有多少个元组(i,j,k,l),
* 使A[i]+B[j]+C[k]+D[I]=0
*/
public class temp011 {
static int fourSumCount(int[] nums1,int[] nums2,int[] nums3,int[] nums4){
Map<Integer,Integer> map = new HashMap<>();
int temp;
int res = 0;
//统计两个数组中的元素之和,同时统计出现的次数,放入map
for (int i:nums1){
for (int j :
nums2) {
temp = j + i;
if (map.containsKey(temp)){
map.put(temp,map.get(temp)+1);
}else{
map.put(temp,1);
}
}
}
//统计剩余的两个元素的和,在map中找是否存在相加为0的情况,同时记录次数
for (int i :
nums3) {
for (int j :
nums4) {
temp = i + j;
if (map.containsKey(0-temp)){
res += map.get(0 - temp);
}
}
}
return res;
}
public static void main(String[] args) {
int[] arr1 = {-1,2,3,4};
int[] arr2 = {1,-2,3,4};
int[] arr3 = {1,2,-3,4};
int[] arr4 = {1,2,3,-4};
int i = fourSumCount(arr1, arr2, arr3, arr4);
System.out.println(i);//i个元组
}
}
三数之和
package Temp;
/*
* @Author: jun
* @Date:2023/2/17 17:30
* @概述:
*/
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 三数之和
* 给定一个包含n个整数的数组nums,判断nums中是否存在三个元素a,b,c,使得a+b+c=0
* 需要找出不可以重复的三元组。
*
* 总共三个数:i,left,right
* i是nums里遍历的元素,重复了的话就直接跳过去
* 虽然不能有重复的三元组,但三元组内的元素是可以重复
*
* left与right的去重
*/
public class temp012 {
static List<List<Integer>> threeSum(int[] nums){
List<List<Integer>> result = new ArrayList<>();
Arrays.sort(nums);//将数组排序
//求a + b + c = 0;
//a = nums[i],b = nums[left], c = nums[right]
for (int i = 0; i < nums.length; i++) {
//排序之后如果第一个元素大于零,则说明无论如何组合都不可能三个数和为0
if (nums[i]>0){
return result;
}
if (i > 0 &&nums[i] == nums[i-1]){
continue;//去重a
}
int left = i+1;//左指针起始位置
int right = nums.length-1;//右指针至于最右侧
while(right>left){
int sum = nums[i] + nums[left] + nums[right];
if (sum>0){
right--;
}else if (sum < 0){
left++;
}else{
result.add(Arrays.asList(nums[i],nums[left],nums[right]));
//去重逻辑应该放在找到一个三元组之后,对b和c去重
while(right>left&&nums[right] == nums[right-1])right--;
while(right>left&&nums[right] == nums[left+1])left--;
right--;
left++;
}
}
}
return result;
}
public static void main(String[] args) {
int[] arr = {-1,0,1,2,-1,-4};
List<List<Integer>> lists = threeSum(arr);
System.out.println(lists);
}
}
反转字符串
package Temp;
/*
* @Author: jun
* @Date:2023/2/18 10:19
* @概述:
*/
/**
* 反转字符串
* 编写一个函数,作用是将输入的字符串反转过来,输入字符串以字符数组char[]的形式给出
* 要求是不使用额外的数组分配空间,你必须原地修改数组
*
*/
public class temp013 {
static char[] reverseString(char[] s){
int l = 0;
int r = s.length - 1;
while(l<r){
s[l] ^= s[r];//构造a^b,并放在a中
s[r] ^= s[l];//将a^b 这一结果再^b,此时b = a,a = a^b
s[l] ^= s[r];//a^b的结果再^a,存入a中,此时b = a,a=b
//完成交换后移动两个指针
l++;//左指针右移
r--;//右指针左移
}
return s;
}
public static void main(String[] args) {
char[] arr = {'A','B','C','D'};
char[] chars = reverseString(arr);
System.out.println(chars);
}
}
反转字符串II
package Temp;
/*
* @Author: jun
* @Date:2023/2/18 10:50
* @概述:
*/
/**
* 反转字符串II
* 给定一个字符串s和一个整数k,从字符串开头算起,每计数至2k个字符,就反转这2k个字符中的前k个字符
* 如果剩余字符小于k个,则将剩余字符全部反转
* 如果剩余字符小于2k但大于或等于k个,则反转前k个字符,其余字符保持原样。
*/
public class temp014 {
static String reverseStr(String s,int k){
StringBuffer res = new StringBuffer();
int length = s.length();
int start = 0;
while(start < length){
//找到每次需要反转得中点k,还有末尾2k
StringBuffer temp = new StringBuffer();//新建一个可变字符串stringBuffer
//与length进行判断,如果大于length了,那就将其置为length
int firstK = (start + k >length)?length : start+k;
int secondK = (start + (2*k)>length)?length : start +(2*k);
//无论start所处的位置,至少会反转一次
temp.append(s.substring(start,firstK));//获取从start到firstK的字符
res.append(temp.reverse());//使用stringBuffer自带的反转方法反转
//如果firstK到secondK之间有元素,这些元素直接放入res里即可
if (firstK < secondK){
res.append(s.substring(firstK,secondK));
}
start += (2*k);//当length足够时,更改start的位置为2k
}
return res.toString();
}
public static void main(String[] args) {
int target = 6;
String chars = "adadsfdsvfbsbsrtgbr";
String s = reverseStr(chars, target);
System.out.println(s);
}
}
代码优质自学平台:代码随想录