《Java練習題》Java進階練習題(二)


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

前言:不僅僅要實現,更要提升性能,精益求精,用盡量少的時間復雜度和空間復雜度解決問題。

【程序58】
給定 n 個非負整數 a1,a2,...,an,每個數代表坐標中的一個點?(i,?ai) 。在坐標內畫 n 條垂直線,垂直線 i?的兩個端點分別為?(i,?ai) 和 (i, 0)。找出其中的兩條線,使得它們與?x?軸共同構成的容器可以容納最多的水。
說明:你不能傾斜容器,且?n?的值至少為 2。
圖中垂直線代表輸入數組 [1,8,6,2,5,4,8,3,7]。在此情況下,容器能夠容納水(表示為藍色部分)的最大值為 49。

/**
 * 給定 n 個非負整數 a1,a2,...,an,每個數代表坐標中的一個點?(i,?ai) 。在坐標內畫 n 條垂直線,垂直線 i?的兩個端點分別為?(i,?ai) 和 (i, 0)。找出其中的兩條線,使得它們與?x?軸共同構成的容器可以容納最多的水。
 * 說明:你不能傾斜容器,且?n?的值至少為 2。
 * 圖中垂直線代表輸入數組 [1,8,6,2,5,4,8,3,7]。在此情況下,容器能夠容納水(表示為藍色部分)的最大值為 49。
 */
public class Subject58 {
    public static void main(String[] args) {
        int[] arr = new int[]{1,8,6,2,5,4,8,3,7};
        System.out.println(maxArea2(arr));
    }

    /**
     * 求最大面積
     * @param height
     * @return
     */
    public static int maxArea2(int[] height) {
        int maxArea = 0; //最大面積
        int left = 0;
        int right = height.length-1;
        int leftvalue = 0;
        int rightvalue = 0;
        while (left < right){
            if(height[left] < height[right]){
                if(height[left] > leftvalue && height[left]*(right-left) > maxArea){
                    maxArea = height[left]*(right-left);
                }
                leftvalue = height[left];
                left++;
            }else{
                if( height[right] > rightvalue && height[right] * (right - left) > maxArea) {
                    maxArea = height[right] * (right - left);
                }
                rightvalue = height[right];
                right--;
            }
        }
        return maxArea;
    }

    /**
     * 計算最大面積
     * @param height
     * @return
     */
    public static int maxArea(int[] height) {
        int maxArea = 0;
        int tmp0 = 0;
        for (int i = 0; i < height.length; i++) {
            if(height[i] > tmp0){
                tmp0 = height[i];
            }else{
                continue;
            }
            for (int j = height.length-1; j >= 0 && j>i ; j--) {
                if(height[j] >= height[i]){
                    if(height[i]*(j-i) > maxArea){
                        maxArea = height[i]*(j-i);
                        break;
                    }
                }
            }
        }
        tmp0 = 0;
        for (int i = height.length-1; i >=0 ; i--) {
            if(height[i] > tmp0){
                tmp0 = height[i];
            }else{
                continue;
            }
            for (int j = 0; j < height.length && i>j; j++) {
                if(height[j] >= height[i]){
                    if(height[i]*(i-j) > maxArea){
                        maxArea = height[i]*(i-j);
                        break;
                    }
                }
            }
        }
        return maxArea;
    }
}

時間復雜度:O(n)

運行結果:

【程序59】
阿拉伯數字轉羅馬數字,羅馬數字包含以下七種字符: I, V, X, L,C,D 和 M。

import java.util.ArrayList;
import java.util.List;

/**
 * 【程序59】
 * 阿拉伯數字轉羅馬數字,羅馬數字包含以下七種字符: I, V, X, L,C,D 和 M。
 */
public class Subject59 {
    public static void main(String[] args) {
        System.out.println(intToRoman(1994));
    }

    /**
     * 阿拉伯數字轉羅馬數字
     * @param num
     * @return
     */
    public static String intToRoman(int num) {
        List<String> list = new ArrayList<>();
        StringBuilder result = new StringBuilder();
        int i = num;
        int num0 = 1;
        while(i > 0){
            int tmp = i%10;
            if(num0 == 1){
                if(tmp == 4){
                    list.add("IV");
                }else if(tmp == 9) {
                    list.add("IX");
                }else{
                    list.add(AssembleNumber(tmp,"I","V"));
                }
            }else if(num0 == 10){
                if(tmp == 4){
                    list.add("XL");
                }else if(tmp == 9) {
                    list.add("XC");
                }else{
                    list.add(AssembleNumber(tmp,"X","L"));
                }
            }else if(num0 == 100){
                if(tmp == 4){
                    list.add("CD");
                }else if(tmp == 9) {
                    list.add("CM");
                }else{
                    list.add(AssembleNumber(tmp,"C","D"));
                }
            }else{
                list.add(AssembleNumber(tmp,"M",""));
            }
            num0 = num0*10;
            i = i/10;
        }
        for(int index=list.size()-1 ;index >= 0;index--){
            result.append(list.get(index));
        }
        return result.toString();
    }

    /**
     * 轉化
     * @param tmp
     * @param str0
     * @param str1
     * @return
     */
    public static String AssembleNumber(int tmp,String str0,String str1){
        String result = "";
        if(tmp < 4){
            for (int i=1;i <= tmp;i++){
                result = result+str0;
            }
        }else{
            result = result+str1;
            for (int i=1;i <= tmp-5;i++){
                result = result+str0;
            }
        }
        return result;
    }
}

時間復雜度:O(n)

運行結果:

【程序60】
羅馬數字轉阿拉伯數字,羅馬數字包含以下七種字符: I, V, X, L,C,D 和 M。

import java.util.HashMap;
import java.util.Map;

/**
 * 【程序60】
 * 羅馬數字轉阿拉伯數字,羅馬數字包含以下七種字符: I, V, X, L,C,D 和 M。
 */
public class Subject60 {
    public static void main(String[] args) {
        System.out.println(new Subject60().romanToInt("MCMXCIV"));
    }

    static Map<String,Integer> map = new HashMap<>();

    /**
     * 靜態代碼塊加載數據
     */
    static {
        map.put("I",1);
        map.put("II",2);
        map.put("III",3);
        map.put("IV",4);
        map.put("V",5);
        map.put("VI",6);
        map.put("VII",7);
        map.put("VIII",8);
        map.put("IX",9);
        map.put("X",10);
        map.put("XX",20);
        map.put("XXX",30);
        map.put("XL",40);
        map.put("L",50);
        map.put("LX",60);
        map.put("LXX",70);
        map.put("LXXX",80);
        map.put("XC",90);
        map.put("C",100);
        map.put("CC",200);
        map.put("CCC",300);
        map.put("CD",400);
        map.put("D",500);
        map.put("DC",600);
        map.put("DCC",700);
        map.put("DCCC",800);
        map.put("CM",900);
        map.put("M",1000);
        map.put("MM",2000);
        map.put("MMM",3000);
    }

    /**
     * 羅馬數字轉阿拉伯數字
     * @param s
     * @return
     */
    public int romanToInt(String s) {
        // I X C M 分別代表1,10,100,1000
        int result = 0;
        char[] arr = s.toCharArray();
        int lenth = arr.length;

        String tmp = "";
        int index0 = 0;
        for (int i = 0; i < lenth ;) {
            tmp = tmp + arr[i];
            if(map.containsKey(tmp)){
                index0 = map.get(tmp);
                i++;
            }else{
                result = result +index0;
                tmp = "";
                index0 = 0;
            }
        }
        return result+index0;
    }
}

時間復雜度:O(n)

運行結果:

【程序61】
編寫一個函數來查找字符串數組中的最長公共前綴。
如果不存在公共前綴,返回空字符串 ""。

/**
 * 編寫一個函數來查找字符串數組中的最長公共前綴。
 * 如果不存在公共前綴,返回空字符串 ""。
 */
public class Subject61 {

    public static void main(String[] args) {
        String[] strs = new String[]{"f","fl","flight"};
        System.out.println(longestCommonPrefix(strs));
    }

    /**
     * 最長公共前綴
     * @param strs
     * @return
     */
    public static String longestCommonPrefix(String[] strs) {
        String result = "";
        if(strs.length <= 0){
            return result;
        }
        boolean flag;
        char tmp ;
        int index = 0;
        while(true){
            flag = true;
            if(index >= strs[0].length()){
                break;
            }else{
                tmp = strs[0].charAt(index);
            }
            for (int i = 1 ;i < strs.length; i++) {
                if(index >= strs[i].length() || strs[i].charAt(index) != tmp){
                    flag = false;
                    break;
                }
            }
            if(flag){
                result = result+tmp;
            }else{
                break;
            }
            index++;
        }
        return result;
    }
}

時間復雜度:O(Slog(n))

運行結果:

【程序62】
給定一個包含 n 個整數的數組?nums,判斷?nums?中是否存在三個元素 a,b,c ,
使得?a + b + c = 0 ?找出所有滿足條件且不重復的三元組。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 給定一個包含 n 個整數的數組?nums,判斷?nums?中是否存在三個元素 a,b,c ,
 * 使得?a + b + c = 0 ?找出所有滿足條件且不重復的三元組。
 */
public class Subject62 {

    public static void main(String[] args) {
        int[] nums = new int[]{2,-1,-1,0,2,1,1};
        System.out.println(threeSum(nums));
    }

    /**
     * 獲取滿足條件的組合
     * @param nums
     * @return
     */
    public static List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        List<List<Integer>> tuples = new ArrayList<>();

        for(int i = 0; i < nums.length-2; i++){
            if(i > 0 && nums[i-1] == nums[i]) continue; //去重

            int l = i+1, r = nums.length-1;
            if(nums[l] < 0 && Integer.MIN_VALUE-nums[l] > nums[i]) continue; //如果溢出最小值則跳過
            if(nums[i] > 0 && Integer.MAX_VALUE-nums[l] < nums[i]) break; //溢出最大值直接結束,不可能會有新的三元組出現了

            while(l < r){
                if(nums[r] > -nums[i]-nums[l]){
                    while(l < r && nums[r-1] == nums[r]) r--; //右指針去重
                    r--;
                }
                else if(nums[r] < -nums[i]-nums[l]){
                    while(l < r && nums[l+1] == nums[l]) l++; //左指針去重
                    l++;
                }
                else{
                    tuples.add(Arrays.asList(nums[i],nums[l],nums[r]));
                    while(l < r && nums[r-1] == nums[r]) r--; //左指針去重
                    while(l < r && nums[l+1] == nums[l]) l++; //右指針去重
                    r--;
                    l++;
                }
            }
        }
        return tuples;
    }
}

時間復雜度:O(nlogn)

運行結果:

【程序63】
給定一個包括n 個整數的數組nums和 一個目標值target。找出nums中的三個整數,使得它們的和與target最接近。返回這三個數的和。
假定每組輸入只存在唯一答案。

/**
 * 給定一個包括n 個整數的數組nums和 一個目標值target。找出nums中的三個整數,使得它們的和與target最接近。返回這三個數的和。
 * 假定每組輸入只存在唯一答案。
 */
public class Subject63 {
    public static void main(String[] args) {
        int[] arr = new int[]{1,1,1,1};
        int target = 0;
        System.out.println(threeSumClosest(arr,target));
    }

    /**
     * 獲取最接近的三個數之和
     * @param nums
     * @param target
     * @return
     */
    public static int threeSumClosest(int[] nums, int target) {
        int sum = 0;
        if(nums.length<=3){
            for (int i = 0; i < nums.length; i++) {
                sum = sum + nums[i];
            }
            return sum;
        }
        int max = Integer.MAX_VALUE;
        int min = Integer.MIN_VALUE;
        for (int i = 0; i < nums.length-2; i++) {
            for (int j = i+1; j < nums.length-1; j++) {
                for (int k = j+1; k < nums.length; k++) {
                    int tmp = nums[i] + nums[j] + nums[k];
                    if(tmp == target ){
                        return target;
                    }else if(tmp > target){
                        if(tmp < max){
                            max = tmp;
                        }
                    }else{
                        if(tmp > min){
                            min = tmp;
                        }
                    }
                }
            }
        }
        if(max == Integer.MAX_VALUE){
            return min;
        }
        if(min == Integer.MIN_VALUE){
            return max;
        }
        if(Math.abs(max-target) <= Math.abs(target-min)){
            sum = max;
        }else{
            sum = min;
        }
        return sum;
    }
}

時間復雜度:O(n^2)

運行結果:

【程序64】
給定一個僅包含數字 2-9 的字符串,返回所有它能表示的字母組合。
給出數字到字母的映射如下(與電話按鍵相同)。注意 1 不對應任何字母。
備注,每個數字對應的字母為9宮格輸入法。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 給定一個僅包含數字 2-9 的字符串,返回所有它能表示的字母組合。
 * 給出數字到字母的映射如下(與電話按鍵相同)。注意 1 不對應任何字母。
 * 備注,每個數字對應的字母為9宮格輸入法。
 */
public class Subject64 {
    public static void main(String[] args) {
        System.out.println(letterCombinations("23"));
    }

    public static Map<Character,List<Character>> map = new HashMap<>();
    //初始化數據
    static {
        List<Character> list = new ArrayList<>();
        list.add('a');
        list.add('b');
        list.add('c');
        map.put('2',list);
        list = new ArrayList<>();
        list.add('d');
        list.add('e');
        list.add('f');
        map.put('3',list);
        list = new ArrayList<>();
        list.add('g');
        list.add('h');
        list.add('i');
        map.put('4',list);
        list = new ArrayList<>();
        list.add('j');
        list.add('k');
        list.add('l');
        map.put('5',list);
        list = new ArrayList<>();
        list.add('m');
        list.add('n');
        list.add('o');
        map.put('6',list);
        list = new ArrayList<>();
        list.add('p');
        list.add('q');
        list.add('r');
        list.add('s');
        map.put('7',list);
        list = new ArrayList<>();
        list.add('t');
        list.add('u');
        list.add('v');
        map.put('8',list);
        list = new ArrayList<>();
        list.add('w');
        list.add('x');
        list.add('y');
        list.add('z');
        map.put('9',list);
    }

    public static List<String> list;

    /**
     * 處理組合情況
     * @param digits
     * @return
     */
    public static List<String> letterCombinations(String digits) {
        if("".equals(digits)){
            return list;
        }
        list = new ArrayList<>();
        list.add("");
        char[] arr = digits.toCharArray();
        for (int i = 0; i < arr.length ; i++) {
            letterCombinations0(arr[i]);
        }
        return list;
    }

    /**
     * 配合letterCombinations使用
     * @param c
     */
    public static void letterCombinations0(char c){
        List<Character> list0  = map.get(c);
        List<String> listTmp = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            for (int j = 0; j < list0.size(); j++) {
                listTmp.add(list.get(i)+list0.get(j));
            }
        }
        list = listTmp;
    }
}

時間復雜度:O(3N×4M)

運行結果:

【程序65】
給定一個包含n 個整數的數組nums和一個目標值target,判斷nums中是否存在四個元素 a,b,c和 d,使得a + b + c + d的值與target相等?
找出所有滿足條件且不重復的四元組。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 給定一個包含n 個整數的數組nums和一個目標值target,判斷nums中是否存在四個元素 a,b,c和 d,使得a + b + c + d的值與target相等?
 * 找出所有滿足條件且不重復的四元組。
 */
public class Subject65 {
    public static void main(String[] args) {
        int[] arr = new int[]{1, 0, -1, 0, -2, 2};
        System.out.println(fourSum(arr,0));
    }

    /**
     * 4個數之和
     * @param nums
     * @param target
     * @return
     */
    public static List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> lists = new ArrayList<>();
        Arrays.sort(nums);
        int lenths = nums.length;
        if(lenths <= 3){
            return lists;
        }
        int min = nums[0];
        int max = nums[lenths-1];
        int min0 = nums[0] + nums[1];
        int max0 = nums[lenths-1]+nums[lenths-2];
        for (int i = 0; i < lenths; i++) {
            for (int j = i+1; j < lenths; j++) {
                int tmp1 = target - nums[i] - nums[j];
                if(tmp1 > max0){
                    continue;
                }
                if(tmp1 < min0){
                    break;
                }
                for (int k = j+1; k < lenths; k++) {
                    int tmp = target - nums[i] - nums[j] - nums[k];
                    if(tmp > max){
                        continue;
                    }
                    if(tmp < min){
                        break;
                    }
                    for (int l = k+1; l < lenths; l++) {
                        int tmp0 = nums[i] + nums[j] + nums[k] + nums[l];
                        if(target == tmp0){
                            List<Integer> list = new ArrayList<>();
                            list.add( nums[i]);
                            list.add(nums[j]);
                            list.add(nums[k]);
                            list.add(nums[l]);
                            if(!lists.contains(list)){
                                lists.add(list);
                            }
                        }
                    }
                }
            }
        }
        return lists;
    }
}

時間復雜度:O(n3)

運行結果:

【程序66】
給定一個鏈表(單項鏈表),刪除鏈表的倒數第 n 個節點,並且返回鏈表的頭結點。

public class ListNode {
    int val;
    ListNode next;
    ListNode(){

    }
    ListNode(int x) { val = x; }
}
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 *
 * 給定一個鏈表(單項鏈表),刪除鏈表的倒數第 n 個節點,並且返回鏈表的頭結點。
 */
public class Subject66 {
    public static void main(String[] args) {
        ListNode listNode0 = new ListNode(1);
        ListNode listNode1 = new ListNode(2);
        ListNode listNode2 = new ListNode(3);
        ListNode listNode3 = new ListNode(4);
        ListNode listNode4 = new ListNode(5);
        listNode0.next = listNode1;
        listNode1.next = listNode2;
        listNode2.next = listNode3;
        listNode3.next = listNode4;
        ListNode listNode = new Subject66().removeNthFromEnd(listNode0,1);
        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());
    }

    //公共變量
    public static ListNode listNodeTmp;

    /**
     * 刪除倒數N的節點
     * @param head
     * @param n
     * @return
     */
    public ListNode removeNthFromEnd(ListNode head, int n) {
        listNodeTmp = null;
        if(head == null){
            return head;
        }
        int num = nodeNum(head,n);
        if(num == n){
            return head.next;
        }
        return head;
    }

    /**
     * 遞歸獲取節點位置
     * @param head
     * @param n
     * @return
     */
    public int nodeNum(ListNode head,int n){
        int tmp = 0;
        if(head != null){
            tmp = 1+ nodeNum(head.next,n);
            if(tmp == n +1){
                head.next = listNodeTmp;
            }
            if(tmp == n-1){
                listNodeTmp = head;
            }
        }
        return tmp;
    }
}

時間復雜度:O(n)

運行結果:

【程序67】
給定一個只包括 '(',')','{','}','[',']'的字符串,判斷字符串是否有效。
有效字符串需滿足:
左括號必須用相同類型的右括號閉合。
左括號必須以正確的順序閉合。
注意空字符串可被認為是有效字符串。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 【程序67】
 * 給定一個只包括 '(',')','{','}','[',']'的字符串,判斷字符串是否有效。
 * 有效字符串需滿足:
 * 左括號必須用相同類型的右括號閉合。
 * 左括號必須以正確的順序閉合。
 * 注意空字符串可被認為是有效字符串。
 */
public class Subject67 {
    public static void main(String[] args) {
        String s= "[]";
        System.out.println( new Subject67().isValid(s));
    }

    static Map<Character,Character> map = new HashMap<>();

    static {
        map.put('(',')');
        map.put('{','}');
        map.put('[',']');
    }

    /**
     * 后進先匹配原理
     * @param s
     * @return
     */
    public boolean isValid(String s) {
        char[] arr = s.toCharArray();
        if(arr.length <= 0){
            return true;
        }
        List<Character> list = new ArrayList<>();
        for (int i = 0; i < arr.length; i++) {
            if(map.containsKey(arr[i])){
                list.add(arr[i]);
            }else{
                if(list.size() <= 0) {
                    return false;
                }
                if(map.get(list.get(list.size()-1)) == arr[i]){
                    list.remove(list.size()-1);
                }else{
                    return false;
                }
            }
        }
        if(list.size() == 0){
            return true;
        }else {
            return false;
        }
    }
}

時間復雜度:O(n)

運行結果:

以上題目均來自:https://leetcode-cn.com/ ,如果你熱愛編碼,熱愛算法,該網站一定適合你。


免責聲明!

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



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