筆おろし日記 Day1
この記事は、Code Random Recording の 60 日間プログラミング チャレンジに基づいたトピックの説明です.
参加リンクはこちら: https://programmercarl.com/other/xunlianying.html
こんにちは、このコラムでは、問題を磨くための 60 日間の集中トレーニングをお届けします. 問題を磨くことは、誰にとっても最も難しいことです. 問題は臭く、長く、抽象的であり、いくつかの問題は、ましてや読むことができません.というわけで、このコラムでは、あなたが窮地から抜け出し、空腹を一掃し、自分らしくありたいと願っています. なじみのない話題に直面したときに始められないことがないように、よくある面接の質問をすべてマスターしてください. Iまた、誰もが監督することを願っています。0 から 1 までの 60 日間、一緒に
大物になりましょう。
1. Leetcode 704 : 二分探索
トピック リンク:
704. 二分探索
実装バージョン 1:
二分探索の本質は、順序付けられた配列で指定された値を見つけることです
クリをあげましょう:
二分探索のコードは次のようになります
class Solution {
public int search(int[] nums, int target) {
// 1. 参数判断
if(nums == null) {
return -1;
}
// 2. 确定左右边界
int left = 0;
int right = nums.length - 1;
// 3. 进行二分查找
// 循环条件:left 不能跑到 right 右边
while(left <= right) {
// 3.1 求中间结点
int mid = left + ((right - left) >> 1);// 防止越界做的优化
if(nums[mid] < target) {
// 如果中间节点的值比目标值小,那就在中间结点右边找
left = mid + 1;
} else if (nums[mid] > target) {
// 如果中间节点的值比目标值大,那就在中间结点左边找
right = mid - 1;
} else {
// 找到就直接返回
return mid;
}
}
// 没找到的话返回 -1 即可
return -1;
}
}
それから何人かの学生は二分法の他のバージョンを見たので、何が起こっているのでしょうか?
私たちはまだ上記の二分法のコードをお勧めしますが、二分法の他のバージョンについてお話ししましょう.
まず第一に、他のバージョンの右二分法の境界はarr.lengthであり
、それを説明するために絵を描きます.
コードもここに貼り付けられます.
class Solution {
public int search(int[] nums, int target) {
// 1. 参数判断
if(nums == null) {
return -1;
}
// 2. 确定左右边界
int left = 0;
int right = nums.length;
// 3. 进行二分查找
// 循环条件:left 不能跑到 right 右边
while(left < right) {
// 3.1 求中间结点
int mid = left + ((right - left) >> 1);// 防止越界做的优化
if(nums[mid] < target) {
// 如果中间节点的值比目标值小,那就在中间结点右边找
left = mid + 1;
} else if (nums[mid] > target) {
// 如果中间节点的值比目标值大,那就在中间结点左边找
right = mid;
} else {
// 找到就直接返回
return mid;
}
}
// 没找到的话返回 -1 即可
return -1;
}
}
この二分探索問題はとても簡単に完成しました
Extension - Leetcode 35 : 検索挿入位置
トピック リンク: 35. 挿入位置の検索
この質問は、実際には二分探索に基づいて少し内容を追加しています.
この質問の意味は、値を与えることです. 配列にこの値がある場合は、その添字を返します. ある場合はそのような値ではありません。どこに挿入すればよいかは
非常に簡単です。画像を見てみましょう
。コードはここに貼り付けられています。
class Solution {
public int searchInsert(int[] arr, int target) {
// 1. 定义左右下标
int left = 0;
int right = arr.length - 1;
// 2. 开始二分查找元素
// 找到就返回
while(left <= right) {
int mid = left + ((right - left) >> 1);
if(arr[mid] < target) {
left = mid + 1;
} else if (arr[mid] > target) {
right = mid - 1;
} else {
return mid;
}
}
// 3. 此时没找到的话就应该返回它将会被按顺序插入的位置
// 二分查找完成之后,left所在的位置就是他将被按顺序插入的位置
return left;
}
}
拡張 - Leetcode 34 : ソートされた配列内の要素の最初と最後の位置を見つける
トピック リンク: 34. 並べ替えられた配列内の要素の最初と最後の位置を見つける
自分で行うことができます。後でこの質問の問題解決のアイデアとコードを更新します。
2. LeetCode 27: 要素を削除する
トピック リンク: 27. 要素を削除する 要素を削除する
問題には 2 つの解決策があります.
1 つは暴力的であることが保証されており、もう 1 つはダブル ポインターのアイデアによって解決できます. 最初に
暴力的な方法を見てみましょう
.まず、削除する要素を見つける必要があります.次に、外側のレイヤーが配列をループして、削除する要素を見つけます.
ループでは、現在の値が削除する要素であるかどうかを判断します削除したい. その場合, 次のすべてを削除する必要があります.要素は1つずつ前方に覆われています, しかし、まだいくつかの小さな穴があります, 見るために
栗を与えることができます.
コードで
class Solution {
public int removeElement(int[] arr, int val) {
// 1. 参数判断
if(arr == null) {
return -1;
}
// 2. 先将数组长度提取出来,最后好直接返回
int length = arr.length;
// 3. 循环遍历数组
// 注意:这里需要将循环条件写成 <length,因为数组不断删除元素,长度是不断变化的
for(int i = 0;i < length;i++) {
// 当该元素和要删除的值相等,那就让后面所有元素依次向前覆盖
if(arr[i] == val) {
// 再定义一个循环,将后面的元素依次向前覆盖
for(int j = i + 1;j < arr.length;j++) {
arr[j - 1] = arr[j];
}
// 注意:i需要进行--
// 比如:[0,1,2,2,3,0,4,2] 删 2
// 当有连续两个2的时候,i不往前回退,会少删除一个2
i--;
// 删除元素,长度也要减1
length--;
}
}
// 最后返回我们定义的长度即可
return length;
}
}
しかし、この質問のハイライトはダブルポインターアルゴリズムです.配列とリンクリストの操作で
ダブルポインター
ダブルポインター法 (高速および低速ポインター法) が非常に一般的であることを説明しましょう.配列、リンクされたリスト、および文字列が調査されます. すべてのインタビューの質問は、ダブル ポインター法を使用します.
この質問では、高速ポインターと低速ポインターの 2 つのポインターを定義します.
高速ポインターの機能は、配列要素をトラバースし、そうでない要素を見つけることです.削除する値と同じにして配列に入れる スロー
ポインタ 配列の添字となり、ファストから渡された要素を受け取る関数
直上
コードもここにある
class Solution {
public int removeElement(int[] arr, int val) {
// 1. 定义快慢指针
int fast = 0;// 快指针相当于出门挣钱的
int slow = 0;// 慢指针就相当于在家看孩子的
// 2. 让快指针依次往后遍历,遇到不是val的就放到slow身上
for(;fast < arr.length;fast++) {
// 如果 fast 的值不是要删除的,那就把它送给 slow
if(arr[fast] != val) {
// slow记得也要往后移动
arr[slow++] = arr[fast];
}
}
// 3. 最后返回 slow 下标,此时 slow 下标就是新数组的长度
return slow;
}
}
この場合、Leetcodeのブラッシング問題数がまた+1されます~
これで1日目のタスクは完了です~
役に立ったら3回クリックしてください~