《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/ ,如果你熱愛編碼,熱愛算法,該網站一定適合你。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM