基础算法(三)——二分查找和其他部分常见算法题

基础算法三(二分查找和其他部分常见算法题)

二分查找的递归和迭代

   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;
    }
    }


猜你喜欢

转载自blog.csdn.net/sinat_33878878/article/details/79801619