(最新バージョン 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) + "");
}
}