Dachang 및 "Jianzhi 제안"에서 비롯된 Java 어레이 어레이 관련 알고리즘 질문, 추가할 메시지를 남겨주세요~~

Java 언어로 제공되는 배열은 동일한 유형의 고정 크기 요소를 저장하는 데 사용됩니다.

100개의 독립변수 number0, number1, ...., number99를 직접 선언하는 대신 number[100]과 같은 배열 변수를 선언할 수 있습니다. 동적으로 확장할 수 있는 컬렉션인 ArrayList와 달리 배열은 정적이며 배열 인스턴스는 크기가 고정되어 있으며 요소의 유형이 동일하며 한 번 생성되면 용량을 변경할 수 없습니다.

학습을 용이하게 하기 위해 편집기는 배열과 관련된 알고리즘 주제 목록을 구성했습니다.


텍스트

1. 2차원 배열에서 [검색]

주제 설명 : n*m 2차원 배열에서 각 행은 왼쪽에서 오른쪽으로 오름차순으로 정렬되고 각 열은 위에서 아래로 오름차순으로 정렬됩니다. 효율적인 함수를 완성하고 이러한 2차원 배열과 정수를 입력하고 배열에 정수가 포함되어 있는지 확인하십시오.

문제 해결 아이디어 : 더블포인터 방식으로 배열의 우측상단부터 시작하여 목표수보다 작으면 내려가고 목표수보다 크면 왼쪽으로 이동한다.

예시:

입력:
 [ [1, 4, 7, 11, 15],
    [2, 5, 8, 12, 19],
    [3, 6, 9, 16, 22],
    [10, 13, 14, 17, 24] ,
    [18, 21, 23, 26, 30] ]

출력: 주어진 target =  5, return  true;주어진 target =  20, return  false.

    public boolean findNumberIn2DArray(int[][] matrix, int target) {
        if (matrix == null || matrix.length == 0) return false;
        int row = 0;
        int col = matrix.length-1;
        while (row < matrix.length && col >= 0) {
            int temp = matrix[row][col];
            if (temp > target) {
                col--;
            } else if (temp < target){
                row++;
            } else {
                return true;
            }
        }
        return false;
    }

2. 1차원 배열에서 [찾기]

2.1 배열에서 [절반] 이상의 숫자 [찾기]

질문 설명 : 배열 길이의 절반 이상 나오는 숫자가 배열에 있습니다. 그 숫자를 찾으십시오. 배열은 비어 있지 않은 것으로 가정할 수 있으며 주어진 배열에는 항상 대부분의 요소가 있습니다.

문제 해결 아이디어 : 먼저 정렬하십시오. 숫자의 절반 이상이 확실히 중간 요소를 덮을 것입니다. 찾으십시오.

예시:

입력: [1, 2, 3, 2, 2, 2, 5, 4, 2]
출력: 2

    public int majorityElement(int[] nums) {
        Arrays.sort(nums);
        return nums[nums.length/2];
    }

2.2 [찾기] 배열의 [반복] 숫자

제목 설명 : 길이가 n인 배열 nums의 모든 숫자는 0에서 n-1 범위에 있습니다. 배열의 일부 숫자가 반복되지만 몇 개의 숫자가 반복되는지도 모르고, 각 숫자가 몇 번이나 반복되는지도 모릅니다. 배열에서 반복되는 숫자를 찾습니다.

문제 해결 아이디어 : 정렬 후 인접한 두 요소를 비교하고 같으면 반복 요소입니다.

입력: [2, 3, 1, 0, 2, 5, 3]
출력: 2 또는 3


3. [숫자가 나타나는 횟수]

3.1 배열의 [하나] 숫자를 제외하고 다른 모든 숫자는 [두 번] 나타납니다.

질문 설명 : 배열  에서 한 번만 나타나는 숫자를 nums 제외하고 모든 숫자는 두 번 나타납니다 . 한 번만 나오는 번호를 찾으십시오 .

문제 해결 아이디어 : 같은 XOR은 0이고 차이는 1이므로 동일한 두 숫자의 XOR 결과는 0이고 모든 숫자의 XOR 결과는 한 번 나타나는 유일한 숫자여야 합니다.

    public int singleNumber(int[] nums) {
        int num = nums[0];
        for (int i = 1; i < nums.length; i++) {
            num ^= nums[i];
        }
        return num;
    }

3.2 배열의 [하나] 숫자를 제외하고 다른 모든 숫자는 [ 세 번 ] 나타납니다.

질문 설명 : 배열  에서 한 번만 나타나는 숫자를 nums 제외하고 모든 숫자는 세 번 나타납니다 . 한 번만 나오는 번호를 찾으십시오 .

문제 해결 아이디어 : 지도를 사용하여 한 번만 나타나는 숫자를 찾고, 다른 숫자가 몇 번 나오든 상관없이 시도하지만 공간 복잡도는 O(1)이 아닙니다.

    public int singleNumber(int[] nums) {
        List<Integer> list1 = new ArrayList<Integer>();
        Map<Integer, Integer> map = new HashMap<>();
        for (int i : nums) {
            if (list1.contains(i)) {
                map.put(i, i);
            } else {
                list1.add(i);
            }
        }
        for (int j : list1) {
            if (!map.containsKey(j)) {
                return j;
            }
        }  
        return -1;
    }

3.3 배열의 [2]개 숫자를 제외하고 다른 모든 숫자는 [두 번] 나타납니다.

질문 설명 : 정수 배열에서  두 개의 숫자 nums 를 제외한 모든 숫자가 두 번 나타납니다 . 한 번만 나타나는 이 두 숫자를 찾는 프로그램을 작성하십시오. 시간 복잡도는 O(n)이어야 하고 공간 복잡도는 O(1)이어야 합니다.

문제 해결 아이디어 : 단일 포인터 방식, 먼저 정렬한 다음 두 값을 전후 비교하고 같으면 건너뛰고 같지 않으면 이전 목표 값을 출력합니다.

    public int[] singleNumbers(int[] nums) {
        int[] ret = new int[2];
        Arrays.sort(nums);
        int i = 1, index = 0;
        while (i < nums.length) {
            // 与前一个相等就跳过,不等说明i-1是目标数
            if (nums[i] == nums[i-1]) {
                i += 2;
                // 处理目标数字在最后的情况
                if (i == nums.length) {
                    ret[index] = nums[i-1];
                }
            } else {
                ret[index++] = nums[i-1];
                i++;
            }  
        }
        return ret;
    }

3.4  [ 첫 번째] [한 번] 나타나는 문자

주제 설명 : 정수형 배열  nums 에는 한 번만 나타나는 숫자가 여러 개 있으므로 한 번만 나타나는 첫 번째 숫자를 찾습니다.

문제 해결 아이디어 : LinkedHashMap의 질서를 사용하십시오.

    public int FirstNotRepeatingChar(int[] arry) {
        LinkedHashMap<Integer, Integer> linkMap = new LinkedHashMap<>();
        for (int i = 0;i < arry.length;i++) {
            if (linkMap.containsKey(arry[i])) {
                linkMap.put(arry[i], linkMap.get(arry[i]) + 1);
            } else {
                linkMap.put(arry[i], 1);
            }
        }
        Iterator<Map.Entry<Integer, Integer>> it = linkMap.entrySet().iterator();
        while(it.hasNext()) {
            Map.Entry<Integer, Integer> temp = it.next();
            if (temp.getValue() == 1) {
                return temp.getKey();
            }
        }
        return -1;
    }

3.5  [첫 번째] 반복 문자

주제 설명 : 정수 배열에는  nums 여러 번만 나타나는 여러 숫자가 있습니다. 첫 번째 반복 숫자를 찾으십시오.

문제 해결 아이디어 : HashSet의 non-repeatability를 사용하는 것이 HashMap보다 더 편리하고 효율적이다.

    public int findDuplicate(int[] numbers) {
        HashSet<Integer> set = new HashSet<>();
        for (int i : numbers) {
            if (set.contains(i)) {
                return i;
            }
            set.add(i);
        }
        return -1;
    }

4. [병합] 두 개의 정렬된 배열

문제 설명 : 두 개의   정수 배열  합  이 내림차순 으로 지정되고 두 정수 합   이 제공되며   각각은   합계   의 요소 수를 나타냅니다. 병합 된   배열도  내림차순이 되지 않도록 으로 병합 하십시오   .nums1 nums2mnnums1nums2 nums2 nums1

문제 해결 아이디어 : 오름차순이므로 끝에서 최대값을 입력한 다음 역순으로 트래버스하는 것을 고려하십시오.

예시:

입력: nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
출력: [1,2,2,3,5,6]
설명: [1,2,3]과 [2,5,6]을 결합해야 하며 결합된 결과는 [1,2,2,3,5,6]입니다.

    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int end = m+n-1;
        int i = m-1;
        int j = n-1;
        while (j >= 0) {
            if (i >= 0 && nums1[i] > nums2[j]) {
                nums1[end--] = nums1[i--];
            } else  {
                nums1[end--] = nums2[j--];
            }
        }
    }

5. 배열을 [가장 작은 수]로 배열

질문 설명 : 음이 아닌 정수의 배열을 입력하고 배열의 모든 숫자를 숫자로 연결하고 연결할 수 있는 모든 숫자 중 가장 작은 숫자를 인쇄합니다.

문제 해결 아이디어 : 정렬 규칙을 다시 작성합니다. 참고: Array.sort()를 사용하여 정렬할 수 없습니다. 그렇지 않으면 3이 30 앞에 있으므로 330>303이 적합하지 않습니다.

    public String minNumber(int[] nums) {
        if (nums == null || nums.length == 0) return "";
        // 冒泡排序的原理
        for (int i=0;i<nums.length;i++) {
            for (int j=i+1;j<nums.length;j++) {
                if (this.compare(nums[i], nums[j])) {
                    int temp = nums[j];
                    nums[j] = nums[i];
                    nums[i] = temp;
                }
            }
        }
        // 遍历输出结果
        StringBuilder sb = new StringBuilder("");
        for (int i=0;i<nums.length;i++) {
            sb.append(nums[i]+"");
        }
        return sb.toString();
    }
    // 重写比较规则(compare方法拆出来是为了更直观)
    private boolean compare (int a, int b) {
        Long left = Long.valueOf(a + "" + b);
        Long right = Long.valueOf(b + "" + a);
        if (left > right) {
            return true; 
        } else {
            return false; 
        }
    }

6. [괄호] 매칭 문제

질문 설명:'('  sum  만 포함된 문자열이 주어지면  ')' 가장 긴 유효한(정형화된 연속적인) 괄호 부분 문자열의 길이를 찾으십시오.

아이디어: 스택의 특성을 활용하여 스택 맨 아래에 추가 숫자를 채워 값을 저장합니다.

예시:

입력: s = ")()())"
출력: 4
설명: 가장 긴 유효한 괄호로 묶인 부분 문자열은 "()()"

    public int longestValidParentheses(String s) {
        int maxNum = 0;
        Stack<Integer> stack = new Stack<Integer>();
        stack.push(-1);

        // 栈里:有多少'(',就需要多少')'
        // 栈底存储上一次满足匹配位置的元素下标,用于计算长度
        for (int i = 0;i < s.length();i++) {
            if (s.charAt(i) == '(') {
                stack.push(i);
            } else {
                stack.pop();
                if (stack.isEmpty()) {
                    stack.push(i);
                } else {
                    // 下标在这里用来计算匹配长度
                    maxNum = Math.max(maxNum, i-stack.peek());
                }
            }
        }
        return maxNum;
    }

7. 가장 긴 [회문 부분 문자열] 찾기 #

주제 설명: 문자열 s가 주어지면 s의 최대 길이가 1000을 초과하지 않는다고 가정하고 s에서 가장 긴 회문 부분 문자열을 찾습니다. 팁:  회문 문자열: 정방향 및 역방향 읽기는 모두 동일합니다.

아이디어: 동적 프로그래밍의 아이디어, 다른 방법은 다음 블로그 게시물을 볼 수 있습니다.

예시:

입력: s = "babad"
출력: "bab"
설명: "aba"도 질문의 의미와 일치하는 답변입니다.

    public String longestPalindrome(String s) {
        if (s.isEmpty()) return s;
        int len = s.length();
        boolean[][] dp = new boolean[len][len];
        int left = 0, right = 0;
        // 倒序向前遍历
        for (int i = len - 2; i >= 0; i--) {
            for (int j = i + 1; j < len; j++) {
                // 小于3一定是回文,aa或aba
                dp[i][j] = s.charAt(i) == s.charAt(j) && ( j-i < 3 || dp[i+1][j-1]);
                // 更新左右边界
                if(dp[i][j] && right-left < j-i){
                    left = i;
                    right = j;
                }
            }
        }
        return s.substring(left,right+1);
    }

LeetCode[5] - 가장 긴 회문 부분 문자열 찾기 및 동적 프로그래밍 및 재귀 및 폭력적 열거


8. 연속된 하위 배열의 [최대 합] #

주제 설명: 정수 배열을 입력하고 배열에 양수와 음수가 있고 배열에서 하나 또는 여러 개의 연속 정수가 하위 배열을 형성하고 연속 하위 배열의 최대 합을 찾습니다.

아이디어: 동적 프로그래밍, 합계가 0보다 작으면 최대 합계가 현재 값으로 설정되고, 그렇지 않으면 최대 합계가 계산됩니다.

    public int maxSubArray(int[] nums) {
        if (nums == null || nums.length == 0) {
            return 0;
        }
        int sum = nums[0];
        int result = nums[0];
        for (int num : nums) {
            // 如果 sum + num < num,说明前面的计算结果 sum 没有意义,所以要换掉
            sum = sum > 0 ? sum + num : num;
            // result永远保存最大值 
            result = Math.max(sum, result);
        }
        return result;
    }

9. 배열에서 [짝수] 앞에 [홀수]를 #

주제 설명 : 정수 배열을 입력하고 모든 홀수가 배열의 전반부에 있고 모든 짝수가 배열의 후반부에 있도록 배열의 숫자 순서를 조정하는 함수를 구현하고 다음을 확인합니다. 홀수와 홀수, 짝수와 짝수 사이의 상대 위치는 변경되지 않습니다. 요구 사항: 시간 복잡도 O(n), 공간 복잡도 O(1)

문제 해결 아이디어 : 버블링의 원리, 짝수를 만나면 끝까지 버블링됩니다 .

    public void reOrderArray_2(int[] array) {
        if (array == null || array.length == 0) return;
        int i = 0, index = 0;
        int len = array.length - 1;
        while(i < len - index){
            if (array[i] % 2 == 0) {
                for (int j = i; j < array.length - 1;j++) {
                    int temp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = temp;
                }
                index ++;
            }
            i++;
        }
    }

10. 두 배열의 [일치하는] 부분과 [일치하지 않는] 부분

주제 설명 : A국과 B국은 전쟁 중이며 그들의 목표는 n개의 땅입니다. A국은 n개의 토지 중 p개의 토지를 얻고자 하고, B국은 n개의 토지 중 q개의 토지를 얻고자 한다. A국만이 원하는 토지의 수, B국만이 원하는 토지의 수, 양국이 원하는 토지의 수를 계산해야 합니다.

문제 해결 아이디어 : 먼저 정렬한 다음 이중 포인터 방식으로 동일한 부분을 가져옵니다.

    public int[] samedrome(int[] country_a, int[] country_b){
        int[] result = new int[3];
        Arrays.sort(country_a);
        Arrays.sort(country_b);

        // i是A指针,j是B指针,index是重合部分的长度
        int i=0, j=0, index=0;
        while (i < country_a.length && j < country_b.length) {
            if (country_a[i] > country_b[j]) {
                j++;
            } else if (country_a[i] < country_b[j]) {
                i++;
            } else {
                i++;
                j++;
                index++;
            }
        }
        result[0] = country_a.length - index;  // a
        result[1] = country_b.length - index;  // b
        result[2] = index;  // 重合
        return result;
    }

11. 곱이 가장 작은 두 수 찾기

제목 설명 : [증가 정렬]의 배열과 숫자 S를 입력하고, 그 합이 정확히 S가 되도록 배열에서 두 숫자 를 찾고, 여러 쌍의 숫자의 합이 S와 같으면 둘 중 가장 작은 곱을 출력 숫자 .

문제 해결 아이디어 : 앞과 뒤에서 각각 횡단하는 두 개의 포인터를 정의합니다. 간격이 멀수록 곱이 작아지므로 처음 두 숫자의 곱이 가장 작습니다.

    public ArrayList<Integer> FindNumbersWithSum(int [] array, int sum) {
        ArrayList<Integer> retList = new ArrayList<>();
        if (array == null ) return retList;
        int left = 0;
        int right = array.length - 1;
        while (left < right) {
            int temp = array[left] + array[right];
            if (temp == sum){
                retList.add(array[left]);
                retList.add(array[right]);
                break;
            } else if (temp < sum) {
                left++;
            } else {
                right--;
            }
        }
        return retList;
    }
       

추천

출처blog.csdn.net/weixin_44259720/article/details/123279873