(最新バージョン 2022 バージョン) Jianzhi 提供検索アルゴリズム ソリューション


1.「Jianzhi offer」のJZ4二次元配列で検索

タイトル説明:

ここに画像の説明を挿入

問題解決のアイデア:

アイデア:
行列の右上隅にある配列を観察します. 数値は現在の列の最小値と現在の行の最小値, つまり行から列への数値の中間値です.の二分探索が使えます。

  • 右上隅から始めて、最初に右上隅の数字を確認し、その数字が探したい数字と同じであれば、検索プロセスは終了します。
  • 現在の数値が目標よりも大きい場合は、数値が配置されている列を削除します。この列の数値は目標よりも大きくなるため、目標は行にのみ表示されます。
  • 現在の数値が目標よりも小さい場合、この行の数値はすべて目標よりも小さいため、数値が配置されている行が削除され、列が検索されます。

プログラムによる実装 (Java):

public class Solution {
    
    
    public boolean Find(int target, int [][] array) {
    
    

        int rows = array.length;
        int cols = array[0].length;
        int row = rows - 1;
        int col = 0;
        while (col < cols && row >= 0) {
    
    
            if (target > array[row][col]) {
    
    
                col++;
            } else if (target < array[row][col]) {
    
    
                row--;
            } else {
    
    
                return true;
            }
        }
        return false;
    }
}

2.「Jianzhi提供」のJZ11ローテーションアレイの最小数

タイトル説明:
ここに画像の説明を挿入

問題解決のアイデア:
配列は、配列の左境界と右境界をそれぞれ表す左ポインターと右ポインターを使用して、インクリメンタルに並べ替えられた回転配列を表し、配列の中央要素の添字 mid = (左 + 右)/2 .

標準の昇順ソート回転配列は常に配列 [左] >= 配列 [右] であり、配列 [左] < 配列 [中] の場合、最小の要素が中央の右側にあることを意味するため、左 = 中; 配列 [ left ] > array[mid]、最小の要素は mid の左側にあるため、right = mid. 左と右が隣接するまでは、array[right] が最小要素です。. ただし、次の 2 つの特殊なケースがあります。

最初のもの、つまり配列の回転は回転なしと同じです。つまり、配列[左] <配列[右]であり、配列[左]はこの時点で最小の要素です。

2 番目のタイプ、array[left] == array[right] == array[mid] このとき、最小の要素は mid の左側または右側にある可能性があります。したがって、現時点では、左と右の間のデータのみをトラバースして、最小の要素を見つけることができます。

プログラミングの実装:

import java.util.ArrayList;
public class Solution {
    
    
    public int minNumberInRotateArray(int [] array) {
    
    
        int l = 0;
        int r = array.length - 1;
        //退出条件:l=r,这时候数组里只剩下一个元素
        while (l < r) {
    
    
            //如果此时数组是严格递增的,直接返回最左边元素
            if (array[l] < array[r]) {
    
    
                return array[l];
            }

            int mid = (l + r) / 2;
            //array[mid] > array[l],说明mid在左边,更新l
            if (array[mid] > array[l]) {
    
    
                l = mid + 1;
                //array[mid] < array[l],说明mid在右边,更新r
            } else if (array[mid] < array[l]) {
    
    
                r = mid;
                //mid=l,说明左边有连续多个相同的值,l后移一位
            } else {
    
    
                l++;
            }
        }
        return array[l];
    }
}

3. JZ38弦の「建治提供」のアレンジ

タイトル説明:

ここに画像の説明を挿入

プログラムによる実装 (Java):

import java.util.*;
public class Solution {
    
    
    ArrayList<String> res = new ArrayList<>();
    ArrayList<Character> list = new ArrayList<>();
    boolean[] visited;
    public ArrayList<String> Permutation(String str) {
    
    
        if (str.length() == 0) {
    
    
            res.add("");
            return res;
        }
        
        visited = new boolean[str.length()];
        char[] chars = str.toCharArray();
        Arrays.sort(chars);
        dfs(chars, 0);

        return res;
    }

    void dfs(char[] arr, int k){
    
    
        //搜索到底,把一条路径加入到res集合中
        if(arr.length == k){
    
    
            res.add(charToString(list));
            return;
        }

        //剪枝。
        for(int i = 0; i < arr.length; i++){
    
    
            //从第二个字符开始,如果连续两个字符一样并且上一个没被访问过,说明arr[i]和arr[i - 1]在同一层,剪枝
            if(i > 0 && arr[i] == arr[i - 1] && visited[i - 1] == false){
    
    
                continue;
            }

            if(visited[i] == false){
    
    
                visited[i] = true;
                list.add(arr[i]);
                dfs(arr, k + 1);
                //回溯
                list.remove(list.size() - 1);
                visited[i] = false;
            }
        }
    }

    //把字符型集合转化为字符串
    String charToString(ArrayList<Character> list){
    
    
        StringBuilder str = new StringBuilder();
        for(int i = 0; i < list.size(); i++){
    
    
            str.append(list.get(i));
        }
        return str.toString();
    }
}

4.「Jianzhi offer」のJZ44番号シーケンスの特定の番号

タイトル説明:
ここに画像の説明を挿入

問題解決のアイデア:
たとえば、1001 桁を見つけるには、
1) 1 桁の値は 10 個あります: 0 ~ 9、その数は 10 × 1 = 10、明らかに 1001 > 10、これらの 10 個の値をスキップして、見てください。後ろの 991 桁目 (1001-10) の数字。
2) 90 個の 2 桁の数字があります: 10 ~ 99、数字は 90 × 2 = 180 で、991 > 180、811 番目 (991-180) の数字を後ろから探し続けます。
3) 3 桁の値は 100 ~ 999 の 900 個あり、その数は 900 × 3 = 2700 であり、811 < 2700 であり、811 桁目が 3 桁の値であることを示します。811=270×3+1 なので、811 桁目は 100 から始まる 270 番目の値で、370 の 2 番目の数である 7 です。
この規則に従って、他の数を取得できます。
プログラミングの実装 (Java):

import java.util.*;


public class Solution {
    
    
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param n int整型
     * @return int整型
     */
    public int findNthDigit (int n) {
    
    
        // write code here
        //bit记录某个数字是多少位的:123是3位,12是2位
        int bit = 1;
        //初始值:1~9为1,10~99为10,100~999为100
        long start = 1;
        //某个范围有多少个数字,1~9有9个,10~99有90个,100~999有900个
        long count = 9;
        if (n == 0) {
    
    
            return 0;
        }

        //找出是多少位的(范围)
        while (n > count) {
    
    
            n -= count;
            bit++;
            start *= 10;
            count = bit * start * 9;
        }

        //找出具体是那个数字
        String num = (start + (n - 1) / bit) + "";
        //获取那个数字的下标
        int index = (n - 1) % bit;
        return Integer.parseInt(num.charAt(index) + "");
    }
}

おすすめ

転載: blog.csdn.net/weixin_51405802/article/details/127646780