• 《Java练习题》Java进阶练习题(一)


    编程合集: https://www.cnblogs.com/jssj/p/12002760.html

    前言:不仅仅要实现,更要提升性能,精益求精,用尽量少的时间复杂度和空间复杂度解决问题。

    【程序48】
    给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标

    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 【程序48】
     * 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标
     */
    public class Subject48 {
        public static void main(String[] args) {
            int[] nums = new int[]{1,4,5,6,7,9,76,43,22,11};
            int target = 11;
            int[] result = twoSum(nums,target);
            for (int i = 0; i < result.length; i++) {
                System.out.println(result[i]);
            }
        }
    
        /**
         * 获取满足条件的数组下标
         * @param nums
         * @param target
         */
        private static int[] twoSum(int[] nums, int target) {
            int[] temp = new int[2];
            Map<Integer,Integer> map = new HashMap<>();
            //遍历查找
            for(int i = 0; i < nums.length; i++){
                int a = nums[i];
                //判断键值是否存在
                if(map.containsKey(target - a)){
                    temp[0] = map.get(target - a);
                    temp[1] = i;
                    return temp;
                }else {//如果找不到则存进去
                    map.put(nums[i], i);
                }
            }
            return null;
        }
    }

    时间复杂度为 O(n)。

    运行结果:

    【程序49】
    给出两个非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字。
    如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
    您可以假设除了数字 0 之外,这两个数都不会以 0开头。

    public class ListNode {
        int val;
        ListNode next;
        ListNode(){
    
        }
        ListNode(int x) { val = x; }
    }
    /**
     * 【程序49】
     * 给出两个非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字。
     * 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
     * 您可以假设除了数字 0 之外,这两个数都不会以 0开头。
     *
     * public class ListNode {
     * int val;
     * ListNode next;
     * ListNode(int x) { val = x; }
     }
     */
    public class Subject49 {
        public static void main(String[] args) {
            ListNode l1 = new ListNode(2);
            ListNode l12 = new ListNode(4);
            ListNode l13 = new ListNode(3);
            l1.next = l12;
            l12.next = l13;
    
            ListNode l2 = new ListNode(5);
            ListNode l21 = new ListNode(6);
            ListNode l22 = new ListNode(4);
            l2.next = l21;
            l21.next = l22;
    
            ListNode listNode = addTwoNumbers(l1,l2);
            StringBuilder stringBuilder = null;
            while(listNode !=null){  //指向位置是否为空
                if(stringBuilder == null){
                    stringBuilder = new StringBuilder();
                    stringBuilder.append(listNode.val);
                }else{
                    stringBuilder.append(" -> "+ listNode.val);
                }
                listNode = listNode.next;    // 指向下一个节点
            }
            System.out.println(stringBuilder.toString());
        }
    
        /**
         * 链表输出和
         * @param l1
         * @param l2
         * @return
         */
        public static ListNode addTwoNumbers(ListNode l1, ListNode l2){
            int carry = 0;   //进位
            ListNode newListNode = new ListNode(0);
            ListNode tmpListNode ;
            tmpListNode = newListNode;
            while(true){
                ListNode listNode = new ListNode(0);
                int tmp = l1.val + l2.val + carry;
                if(tmp < 10){
                    listNode.val = tmp;
                    carry = 0;
                }else{
                    listNode.val = tmp%10;
                    carry = 1;
                }
                tmpListNode.next = listNode;
                tmpListNode = listNode;
                if(l1.next ==null && l2.next == null &&carry == 0){
                    break;
                }
                if(l1.next != null){
                    l1 = l1.next;
                }else{
                    l1 = new ListNode(0);
                }
                if( l2.next != null){
                    l2 = l2.next;
                }else{
                    l2 = new ListNode(0);
                }
            }
            return newListNode.next;
        }
    }

    时间复杂度:O(max(m, n))

    运行结果:

    【程序50】
    给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。

    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。
     */
    public class Subject50 {
        public static void main(String[] args) {
            String Str = "aabcdfffwwesdwhjkl";
            int count = lengthOfLongestSubstring(Str);
            System.out.println(count);
        }
    
        /**
         * 获取字符最大长度
         * @param s
         * @return
         */
        public static int lengthOfLongestSubstring(String s) {
            char[] arr = s.toCharArray();
            List<Character> list = new ArrayList<>();
            int maxCount = 0;
            int count;
            for (int i = 0; i < arr.length; i++) {
                if(list.contains(arr[i])){
                    count = list.size();
                    if(count> maxCount){
                        maxCount = count;
                    }
                    for (int j = 0; j < list.size(); j++) {
                        if(list.get(j) != arr[i]){
                            list.remove(j);
                            j--;
                        }else{
                            list.remove(j);
                            break;
                        }
                    }
                    list.add(arr[i]);
                }else{
                    list.add(arr[i]);
                }
            }
            if(list.size() > maxCount){
                return list.size();
            }else{
                return maxCount;
            }
        }
    }

    时间复杂度:O(n)

    运行结果:

    【程序51】
    给定两个大小为 m 和 n 的有序数组nums1 和nums2。
    请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为O(log(m + n))。
    你可以假设nums1和nums2不会同时为空

    /**
     * 给定两个大小为 m 和 n 的有序数组nums1 和nums2。
     * 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为O(log(m + n))。
     * 你可以假设nums1和nums2不会同时为空
     */
    public class Subject51 {
        public static void main(String[] args) {
            int[] nums1 = new int[]{1,2,3};
            int[] nums2 = new int[]{1,2};
            double arr = findMedianSortedArrays(nums1,nums2);
            System.out.println(arr);
        }
    
        public static int PartSort(int arr[], int low, int high) {
            int data = arr[low];
            /**一次遍历的方法:插空法 定义一个data将arr[low]存起来,并把这个位置挖空*/
            while (low < high) {
                while (low < high && arr[high] >= data) {
                    high--;
                }
                arr[low] = arr[high];
                /**从high,也就是后面往前遍历 找到比键值小的数据 插入到前面留下的空中 high位再次留下空来*/
                while (low < high && arr[low] <= data) {
                    low++;
                }
                arr[high] = arr[low];
            }
            arr[low] = data;
            /**循环退出后 low和high重合 将将键值赋给第low,并将low返回*/
            return low;
        }
    
    
        /**
         * 快速排序法
         * @param arr
         * @param low
         * @param high
         */
        public static void quickSort(int arr[], int low, int high) {
            if(low<high) {
                //防止发生栈溢出异常
                int index = PartSort(arr, low, high);
                quickSort(arr, low, index - 1);
                quickSort(arr, index + 1, high);
            }
        }
    
        /**
         * 寻找中位数
         * @param nums1
         * @param nums2
         * @return
         */
        public static double findMedianSortedArrays(int[] nums1, int[] nums2) {
            int a = nums1.length;
            int b = nums2.length;
            int[] arr = new int[a+b];
            double result = 0.0;
            if(a >= 2 && b >=2 ){
                if(nums1[0] <= nums1[1] && nums2[0] <= nums2[1] ){
                    if(nums1[0] >= nums2[0]){
                        for (int i = 0; i < b; i++) {
                            arr[i] = nums2[i];
                        }
                        for (int i = 0; i < a; i++) {
                            arr[i+b] = nums1[i];
                        }
                    }else{
                        for (int i = 0; i < a; i++) {
                            arr[i] = nums1[i];
                        }
                        for (int i = 0; i < b; i++) {
                            arr[i+a] = nums2[i];
                        }
                    }
                }else if(nums1[0] >= nums1[1] && nums2[0] >= nums2[1]){
                    if(nums1[a-1] <= nums2[b-1]){
                        for (int i = 0; i < a; i++) {
                            arr[i] = nums1[a-i-1];
                        }
                        for (int i = 0; i < b; i++) {
                            arr[i+a] = nums2[b-i-1];
                        }
                    }else{
                        for (int i = 0; i < b; i++) {
                            arr[i] = nums1[b-i-1];
                        }
                        for (int i = 0; i < a; i++) {
                            arr[i+b] = nums2[a-i-1];
                        }
                    }
                }else if(nums1[0] <= nums1[1] && nums2[0] >= nums2[1]){
                    if(nums1[0] <= nums2[b-1]){
                        for (int i = 0; i < a; i++) {
                            arr[i] = nums1[i];
                        }
                        for (int i = 0; i < b; i++) {
                            arr[i+a] = nums2[b-i-1];
                        }
                    }else{
                        for (int i = 0; i < b; i++) {
                            arr[i] = nums2[i];
                        }
                        for (int i = 0; i < a; i++) {
                            arr[i+b] = nums1[a-1-i];
                        }
                    }
                }else if(nums1[0] >= nums1[1] && nums2[0] <= nums2[1]){
                    if(nums1[a-1] <= nums2[0]){
                        for (int i = 0; i < a; i++) {
                            arr[i] = nums1[a-1-i];
                        }
                        for (int i = 0; i < b; i++) {
                            arr[i+a] = nums2[i];
                        }
                    }else{
                        for (int i = 0; i < b; i++) {
                            arr[i] = nums2[i];
                        }
                        for (int i = 0; i < a; i++) {
                            arr[i+b] = nums1[a-1-i];
                        }
                    }
                }
            }else{
                for (int i = 0; i < a; i++) {
                    arr[i] = nums1[i];
                }
                for (int i = 0; i < b; i++) {
                    arr[i+a] = nums2[i];
                }
            }
            int right = arr.length-1;
            int left = 0;
    
            quickSort(arr,left,right);
    
            int tmp = arr.length;
            if(tmp % 2 == 0){
                result = (arr[tmp/2] + arr[tmp/2 - 1]) / 2.0;
            }else{
                result = arr[tmp/2];
            }
            return result;
        }
    }

    时间复杂度:O(log(min(m,n)))

    运行结果:

    【程序52】
    给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

    /**
     * 【程序52】
     * 给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
     */
    public class Subject52 {
        public static void main(String[] args) {
            String str = "sdffttrrgfddfh";
            String result= longestPalindrome(str);
            System.out.println(result);
            result = longestPalindrome1(str);
            System.out.println(result);
        }
    
        /**
         * Manacher算法
         * @param str
         * @return
         */
        private static String longestPalindrome1(String str) {
            char[] cStr = str.toCharArray();
            //插入特殊符号
            StringBuffer sBuffer = new StringBuffer();
            sBuffer.append("#");
            for (int i = 0; i < cStr.length; i++) {
                sBuffer.append(cStr[i]);
                sBuffer.append("#");
            }
            int id =0;   //回文的中心。
            int max = 0; //回文最大长度。
            //辅助数组
            int[] p= new int[sBuffer.length()];
            for (int i = 1; i < sBuffer.length(); i++) {
    
                if (i<max) {
                    p[i] = Math.min(p[2*id-i], max-i);
                }else {
                    p[i]= 1;
                }
                //判断中心两边是否回文,是则++;
                while (i-p[i]>=0&&i+p[i]<sBuffer.length()&&sBuffer.charAt(i-p[i])==sBuffer.charAt(i+p[i])) {
                    p[i]++;
                }
                if (i+p[i]>max) {
                    max = i+p[i];
                    id = i;
                }
            }
            int maxl = 0 ;
            int maxid =0 ;
            for(int i =0 ;i<p.length;i++){
                if(maxl<p[i]){
                    maxl=p[i];
                    maxid = i;
                }
            }
            //半径包括id本身。id到第一个元素,id-r+1
            int r = maxl-1;
            int start = maxid-r+1;
            int end = maxid+maxl-1;
            StringBuffer out = new StringBuffer();
            for (int i = start; i < end; i++) {
                if (sBuffer.charAt(i)!='#') {
                    out.append(sBuffer.charAt(i));
                }
            }
            return out.toString();
        }
    
    
        /**
         * 获取最长回文数
         * @param s
         * @return
         */
        public static String longestPalindrome(String s) {
            String result = "";
            char[] arr = s.toCharArray();
            for(int i = 0 ; i < arr.length; i++){
                for (int j = 0; j <= i; j++) {
                    //判断是否回文。
                    result =  palindromeStr(s,arr,i,j);
                    if(!"".equals( result) ){
                        return result;
                    }
                }
            }
            return result;
        }
    
        /**
         * 判断字符串是否是回文字符串
         * @param s
         * @param arr
         * @param i
         * @param j
         * @return
         */
        private static String palindromeStr(String s,char[] arr, int i, int j) {
            String result = "";
            int start = j;
            int end = arr.length-(i-j)-1;
            while(start <= end){
                if(arr[start] == arr[end]){
                    if(start+1 >= end){
                        result = s.substring(j,arr.length-(i-j));
                        return result;
                    }
                    start++;
                    end--;
                }else{
                    break;
                }
            }
            return result;
        }
    }

    时间复杂度:O(n

    运行结果:

    【程序53】
    将一个给定字符串根据给定的行数,以从上往下、从左到右进行 || 字形排列

    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 【程序53】
     * 将一个给定字符串根据给定的行数,以从上往下、从左到右进行  字形排列
     *
     * 输入: s = "LEETCODEISHIRING", numRows =4
     * 输出:"LDREOEIIECIHNTSG"
     * 解释:
     *   L     D     R
     *   E   O E   I I
     *   E C   I H   N
     *   T     S     G
     */
    public class Subject53 {
        public static void main(String[] args) {
            String s = "LEETCODEISHIRING";
            int numRows = 4;
            String str = convert(s,numRows);
            System.out.println(str);
        }
    
        /**
         *
         * @param s
         * @param numRows
         * @return
         */
        public static String convert(String s,int numRows){
            if(numRows <= 1){
                return s;
            }
            char[] arr = s.toCharArray();
            //创建numRows个字符串
            List<StringBuilder> list = new ArrayList<>();
            for (int i = 0; i < numRows; i++) {
                StringBuilder stringBuffer = new StringBuilder();
                list.add(stringBuffer);
            }
    
            int flag = 0; // 0表示顺序,1表示逆序。
            int size = 1; //在第几行
            for (int i = 0; i < arr.length; i++) {
                if(size == numRows){
                    flag = 1;
                }
                if(size == 1){
                    flag = 0;
                }
                list.get(size-1).append(arr[i]);
    
                if(flag == 0){
                    size++;
                }
                if(flag == 1){
                    size--;
                }
            }
    
            StringBuilder newStringBuffer = new StringBuilder();
    
            for (int i = 0; i < numRows; i++) {
                newStringBuffer.append(list.get(i));
            }
            return newStringBuffer.toString();
        }
    }

    时间复杂度:O(n)

    运行结果:

    【程序54】
    给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。

    /**
     * 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
     */
    public class Subject54 {
        public static void main(String[] args) {
            int x= 2147483641;
            int result = reverse(x);
            System.out.println(result);
            result = reverse2(x);
            System.out.println(result);
        }
    
        /**
         * 反转
         * @param x
         * @return
         */
        public static int reverse(int x){
            String str = x+"";
            char[] arr = str.toCharArray();
            StringBuilder  stringBuilder =  new StringBuilder();
            if(arr[0] == '-'){
                stringBuilder.append('-');
                for (int i = arr.length-1; i >= 1; i--) {
                    stringBuilder.append(arr[i]);
                }
            }else{
                for (int i = arr.length-1; i >= 0; i--) {
                    stringBuilder.append(arr[i]);
                }
            }
    
            int result = 0;
            try {
                result = Integer.parseInt(stringBuilder.toString());
            }catch (Exception e){
                result = 0;
            }
            return result;
        }
    
        /**
         * 反转2
         * @param x
         * @return
         */
        public static int reverse2(int x){
            int rev = 0;
            while (x != 0) {
                int pop = x % 10;
                x /= 10;
                if (rev > Integer.MAX_VALUE/10 || (rev == Integer.MAX_VALUE / 10 && pop > 7)) return 0;
                if (rev < Integer.MIN_VALUE/10 || (rev == Integer.MIN_VALUE / 10 && pop < -8)) return 0;
                rev = rev * 10 + pop;
            }
            return rev;
        }
    }

    时间复杂度:O(log(x))

    运行结果:

    【程序55】
    请你来实现一个 atoi 函数,使其能将字符串转换成整数。

    /**
     * 【程序55】
     * 请你来实现一个 atoi 函数,使其能将字符串转换成整数。
     */
    public class Subject55 {
        public static void main(String[] args) {
            String str = " -2147483649ww";
            int i= myAtoi(str);
            System.out.println(i);
        }
        public static int myAtoi(String str) {
            int radix = 10;
            if (str == null) {
                return 0;
            }else{
                str = str.trim();
            }
    
            int result = 0;
            boolean negative = false;
            int i = 0, len = str.length();
            int limit = -Integer.MAX_VALUE;
            int multmin;
            int digit;
    
            if (len > 0) {
                char firstChar = str.charAt(0);
                if (firstChar < '0') { // Possible leading "+" or "-"
                    if (firstChar == '-') {
                        negative = true;
                        limit = Integer.MIN_VALUE;
                    } else if (firstChar != '+')
                        return 0;
    
                    if (len == 1) // Cannot have lone "+" or "-"
                        return 0;
                    i++;
                }
                multmin = limit / radix;
                while (i < len) {
                    // Accumulating negatively avoids surprises near MAX_VALUE
                    digit = Character.digit(str.charAt(i++),radix);
                    if (digit < 0) {
                        break;
                    }
                    if (result < multmin) {
                        result = limit;
                        break;
                    }
                    result *= radix;
                    if (result < limit + digit) {
                        result = limit;
                        break;
                    }
                    result -= digit;
                }
            } else {
                return 0;
            }
            return negative ? result : -result;
        }
    }

    时间复杂度:O(n)

    运行结果:

    【程序56】
    判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
    考虑负数。

    /**
     * 【程序56】
     * 判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
     */
    public class Subject56 {
        public static void main(String[] args) {
            int x = 1;
            boolean flag = isPalindrome(x);
            System.out.println(flag);
        }
    
        /**
         * 判断x是否是回文数
         * @param x
         * @return
         */
        public static boolean isPalindrome(int x) {
            if(x < 0){
                return false;
            }
            if(x < 10){
                return true;
            }
            int newi = 0;
            int num = x;
            while(true){
                if(newi>0){
                    newi = newi*10;
                }
                int i = num%10 ;
                newi = newi+i;
                num = num/10;
                if(num <= 9){
                    newi = newi*10+num;
                    break;
                }
            }
            if(newi == x){
                return true;
            }else{
                return false;
            }
        }
    }

    时间复杂度:O(log_{10}(n))

    运行结果:

    【程序57】
    给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。
    '.' 匹配任意单个字符
    '*' 匹配零个或多个前面的那一个元素

    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。
     * '.' 匹配任意单个字符
     * '*' 匹配零个或多个前面的那一个元素
     */
    public class Subject57 {
        public static void main(String[] args) {
            Map<String ,String>  map = new HashMap<>();
            map.put("dddc","d*dddc");    //true;
            for (Map.Entry<String,String> entry :map.entrySet()){
                System.out.println(entry.getKey()+" : "+entry.getValue());
                System.out.println(isMatch(entry.getKey(),entry.getValue()));
            }
        }
    
        /**
         * 实现匹配规则
         * @param s
         * @param p
         * @return
         */
        public static boolean isMatch(String s, String p) {
            if (p.isEmpty()) return s.isEmpty();
            boolean first_match = (!s.isEmpty() &&
                    (p.charAt(0) == s.charAt(0) || p.charAt(0) == '.'));
    
            if (p.length() >= 2 && p.charAt(1) == '*'){
                return (isMatch(s, p.substring(2)) ||
                        (first_match && isMatch(s.substring(1), p)));
            } else {
                return first_match && isMatch(s.substring(1), p.substring(1));
            }
        }
    }

    时间复杂度:O(TP)

    运行结果:

    以上题目均来自:https://leetcode-cn.com/ ,如果你热爱编码,热爱算法,该网站一定适合你。

    This moment will nap, you will have a dream; But this moment study,you will interpret a dream.
  • 相关阅读:
    asp.net 获取当前项目的根目录路径
    asp.net 中 UEditor 图片和附件上传失败的处理方法
    [LOJ#2331]「清华集训 2017」某位歌姬的故事
    [LOJ#2330]「清华集训 2017」榕树之心
    [LOJ#2329]「清华集训 2017」我的生命已如风中残烛
    [LOJ#2328]「清华集训 2017」避难所
    [LOJ#2327]「清华集训 2017」福若格斯
    [LOJ#2326]「清华集训 2017」简单数据结构
    [LOJ#2325]「清华集训 2017」小Y和恐怖的奴隶主
    [LOJ#2324]「清华集训 2017」小Y和二叉树
  • 原文地址:https://www.cnblogs.com/jssj/p/12001585.html
Copyright © 2020-2023  润新知