基础算法三(二分查找和其他部分常见算法题)
二分查找的递归和迭代
import java.util.Scanner;
/**
* 二分查找的递归和迭代,尤其要注意数组越界问题,当数组长度为[1,2]=2时,start=end
* 如果此时 目标查找数 n<array[mid=0]时,那么此时出现start=0,end=-1,继续递归的化
* start!=end,执行下去数组越界,迭代的话,会陷入死循环之类 的,统一判断当发生start=0,end=-1时
* 即为查找不到该数
* @author Shinelon
*
*/
public class HalfSearch {
int [] source = {0,4,8,9,15,41,55,60};
public static void main(String [] args) {
HalfSearch search = new HalfSearch();
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
int rs1 = search.getIndex(t, 0, 7);
int rs2 = search.getIndexOther(t, 0, 7);
System.out.println("递归"+rs1);
System.out.println("迭代"+rs2);
}
//递归实现
public int getIndex(int number,int s, int e) {
if(s>e) {
return -1;
}
int mid = (e+s)>>1;//(s+e)/2;
if(number == source[mid]) {
return mid;
}else if(number>source[mid]) {
return getIndex(number,mid+1,e);
}else {
return getIndex(number,s,mid-1);
}
}
//迭代实现
public int getIndexOther(int number,int s,int e) {
int mid = 0;
while(s<=e) {
mid = (s+e)>>1;// (s+e)/2;
if(source[mid]==number) {
return mid;
}else if(number>source[mid]){
s=mid+1;
}else {
e=mid-1;
}
}
return -1;
}
}
最小栈问题,记录一个栈的当前最小值,出栈入栈数据要更新
如果使用一个临时temp变量入栈时可以更新,出栈就GG了,解决方法,可以使用一个辅助栈,记录当前的主栈的最小值,和主栈同步更新
import java.awt.HeadlessException;
import java.util.Scanner;
import java.util.Stack;
public class TestMinStack {
Stack<Integer> mainStack = new Stack<>();
Stack<Integer> tempStack = new Stack<>();
public static void main(String [] args) {
TestMinStack stack = new TestMinStack();
stack.testMin();
}
public void testMin() {
System.out.println("输入栈的元素6个");
Scanner sc = new Scanner(System.in);
int temp = Integer.MAX_VALUE;
for(int i=0;i<6;i++) {
int num = sc.nextInt();
mainStack.push(num);
if(num<temp) {
temp = num;
}
tempStack.push(temp);
}
for(int j=0;j<6;j++) {
int value = mainStack.pop();
tempStack.pop();
try {
int min = tempStack.peek();
System.out.println("出栈:"+value+"当前栈中最小值:"+min);
}catch(Exception e) {
System.out.println("出栈:"+value+"空栈了没有最小值");
}
}
}
}
找出数组中三数之和为0的所有不重复元素
使用双指针方法,先排序,然后从左右往中间夹,直到找到并遍历完成。注意去重问题,双指针过程中去除重复
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
/**
* 找出数组三数之和为0的元素,不重复,双指针
* @author Shinelon
*
*/
public class TestThreeNum {
public static void main(String [] args) {
Scanner sc = new Scanner(System.in);
TestThreeNum test = new TestThreeNum();
int n = sc.nextInt();
int [] nums = new int[n];
for(int i=0;i<n;i++) {
nums[i]=sc.nextInt();
}
sc.close();
//先排序
Arrays.sort(nums);
List<List<Integer>> rs = test.threeSum(nums);
System.out.println(rs.toString());
}
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> outList = new ArrayList<>();
//如果大于0都是正数,不可能
if(nums[0]>0) {
return outList;
}
for(int i=0;i<nums.length-2;i++) {
//去除重复
if(i>0&&nums[i]==nums[i-1]) {
continue;
}
int j=i+1;
int k=nums.length-1;
while(j<k) {
if(nums[k]+nums[j]+nums[i]>0) {
k--;
}else if(nums[k]+nums[j]+nums[i]<0){
j++;
}else {
List<Integer> list = new ArrayList<>();
list.add(nums[i]);
list.add(nums[j]);
list.add(nums[k]);
outList.add(list);
//继续遍历
k--;
j++;
//去除重复
while(j<k&&nums[j]==nums[j-1]) {
j++;
}
//去除重复
while(j<k&&nums[k]==nums[k+1]) {
k--;
}
}
}
}
return outList;
}
}
n个人围成一圈,玩丢手绢,找出连续m个人记录次数之和最大,比如 1 4 2 3 0 5 为 4 2 3 = 11。记得是顺丰笔试
其实就是找出连续m位和最大,只不过注意是数组是首尾相接的而已
import java.util.Scanner;
public class Main{
public static void main(String [] args){
Main main = new Main();
Scanner sc = new Scanner(System.in);
int number = sc.nextInt();
int [] array = new int [number];
for(int i=0;i<number;i++) {
array[i] = sc.nextInt();
}
int n = sc.nextInt();
sc.close();
int rs = main.getMax(array,number,n);
System.out.println(rs);
}
public int getMax(int [] array,int number,int n) {
if(number==1) {
return array[0];
}
int temp =0;
int dp[] = new int[number];
for(int j=0;j<number;j++) {
dp[j] = array[j];
int m = j-n+1;
while(m%number<j) {
if(m<0) {
m+=3;
}
dp[j] +=array[m];
m++;
}
if(dp[j]>temp) {
temp = dp[j];
}
}
for(int i=0;i<dp.length;i++) System.out.println("dp[i]"+dp[i]);
return temp;
}
}
最长不重复字串
利用HashMap,详细看代码注释
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
/**
* 最长不重复子串O(n)
* HashMap,key为字符,value为索引。当map中不存在时,直接放入,否则取出上一个索引
* 当前减去上一个索引即为当前不重复的最长长度,然后从上一个重复的数的下一个索引开始新一轮比较,
* 也就是去除重复因素的影响,将开始start+1索引。若不存在,放入之后更新长度值,也就是-start+1
* @author Shinelon
*
*/
public class TestMaxChildString {
public static void main(String [] args) {
TestMaxChildString test = new TestMaxChildString();
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
sc.close();
int rs = test.lengthOfLongestSubstring(s);
System.out.println(rs);
}
public int lengthOfLongestSubstring(String s) {
char [] c = s.toCharArray();
Map<Character,Integer> map = new HashMap<>();
int max=0;//最大值
int start=0;//寻找不重复字串长度开始的索引
for(int i=0;i<c.length;i++) {
if(map.containsKey(c[i])) {
//temp>=start,说明在寻找的合法范围内
int temp =map.get(c[i]);
if(temp>=start) {
//更新,两个之间的差值即为不重复长度
max = Math.max(i-temp,max);
//后移一位,因为前面已经重复了,构造新的不重复串并继续比较,后面可能出现更长的不重复
start = temp+1;
//更新当前的索引,消除前面那个重复数的影响,因为构造的是不重复的新串
map.put(c[i], i);
}else {//不存在,则放入并更新值
map.put(c[i], i);
int rs = i-start+1;
max = Math.max(max, rs);
}
}else {
map.put(c[i], i);
int rs = i-start+1;
max = Math.max(max, rs);
}
}
return max;
}
}