Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 8c2737d

Browse files
Merge branch 'master' into patch08
2 parents 16c6abf + f03f8d2 commit 8c2737d

File tree

82 files changed

+2745
-307
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+2745
-307
lines changed

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@
254254
33. [二叉树:构造一棵搜索树](./problems/0108.将有序数组转换为二叉搜索树.md)
255255
34. [二叉树:搜索树转成累加树](./problems/0538.把二叉搜索树转换为累加树.md)
256256
35. [二叉树:总结篇!(需要掌握的二叉树技能都在这里了)](./problems/二叉树总结篇.md)
257-
257+
258258
## 回溯算法
259259

260260
题目分类大纲如下:

‎problems/0001.两数之和.md‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ class Solution {
274274
}
275275
}
276276
```
277+
277278
Scala:
278279
```scala
279280
object Solution {
@@ -296,5 +297,26 @@ object Solution {
296297
}
297298
}
298299
```
300+
301+
C#:
302+
```csharp
303+
public class Solution {
304+
public int[] TwoSum(int[] nums, int target) {
305+
Dictionary<int ,int> dic= new Dictionary<int,int>();
306+
for(int i=0;i<nums.Length;i++){
307+
int imp= target-nums[i];
308+
if(dic.ContainsKey(imp)&&dic[imp]!=i){
309+
return new int[]{i, dic[imp]};
310+
}
311+
if(!dic.ContainsKey(nums[i])){
312+
dic.Add(nums[i],i);
313+
}
314+
}
315+
return new int[]{0, 0};
316+
}
317+
}
318+
```
319+
320+
299321
-----------------------
300322
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

‎problems/0015.三数之和.md‎

Lines changed: 26 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -313,54 +313,36 @@ func threeSum(nums []int)[][]int{
313313
javaScript:
314314

315315
```js
316-
/**
317-
* @param {number[]} nums
318-
* @return {number[][]}
319-
*/
320-
321-
// 循环内不考虑去重
322-
var threeSum = function(nums) {
323-
const len = nums.length;
324-
if(len < 3) return [];
325-
nums.sort((a, b) => a - b);
326-
const resSet = new Set();
327-
for(let i = 0; i < len - 2; i++) {
328-
if(nums[i] > 0) break;
329-
let l = i + 1, r = len - 1;
330-
while(l < r) {
331-
const sum = nums[i] + nums[l] + nums[r];
332-
if(sum < 0) { l++; continue };
333-
if(sum > 0) { r--; continue };
334-
resSet.add(`${nums[i]},${nums[l]},${nums[r]}`);
335-
l++;
336-
r--;
337-
}
338-
}
339-
return Array.from(resSet).map(i => i.split(","));
340-
};
341-
342-
// 去重优化
343316
var threeSum = function(nums) {
344-
const len = nums.length;
345-
if(len <3) return [];
346-
nums.sort((a, b) => a - b);
347-
constres= [];
348-
for(let i = 0; i <len - 2; i++) {
349-
if(nums[i] >0) break;
350-
// a去重
351-
if(i >0&& nums[i] === nums[i -1]) continue;
352-
let l = i +1, r = len - 1;
317+
const res= [], len = nums.length
318+
// 将数组排序
319+
nums.sort((a, b) => a - b)
320+
for (let i =0; i < len; i++) {
321+
let l = i +1, r =len - 1, iNum = nums[i]
322+
// 数组排过序,如果第一个数大于0直接返回res
323+
if (iNum >0) return res
324+
// 去重
325+
if (iNum == nums[i - 1]) continue
353326
while(l < r) {
354-
const sum = nums[i] + nums[l] + nums[r];
355-
if(sum < 0) { l++; continue };
356-
if(sum > 0) { r--; continue };
357-
res.push([nums[i], nums[l], nums[r]])
358-
// b c 去重
359-
while(l < r && nums[l] === nums[++l]);
360-
while(l < r && nums[r] === nums[--r]);
327+
let lNum = nums[l], rNum = nums[r], threeSum = iNum + lNum + rNum
328+
// 三数之和小于0,则左指针向右移动
329+
if (threeSum < 0) l++
330+
else if (threeSum > 0) r--
331+
else {
332+
res.push([iNum, lNum, rNum])
333+
// 去重
334+
while(l < r && nums[l] == nums[l + 1]){
335+
l++
336+
}
337+
while(l < r && nums[r] == nums[r - 1]) {
338+
r--
339+
}
340+
l++
341+
r--
342+
}
361343
}
362344
}
363-
return res;
345+
return res
364346
};
365347
```
366348
TypeScript:

‎problems/0019.删除链表的倒数第N个节点.md‎

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939

4040
分为如下几步:
4141

42-
* 首先这里我推荐大家使用虚拟头结点,这样方面处理删除实际头结点的逻辑,如果虚拟头结点不清楚,可以看这篇: [链表:听说用虚拟头节点会方便很多?](https://programmercarl.com/0203.移除链表元素.html)
42+
* 首先这里我推荐大家使用虚拟头结点,这样方便处理删除实际头结点的逻辑,如果虚拟头结点不清楚,可以看这篇: [链表:听说用虚拟头节点会方便很多?](https://programmercarl.com/0203.移除链表元素.html)
4343

4444
* 定义fast指针和slow指针,初始值为虚拟头结点,如图:
4545

@@ -289,6 +289,28 @@ func removeNthFromEnd(_ head: ListNode?, _ n: Int) -> ListNode? {
289289
return dummyHead.next
290290
}
291291
```
292-
292+
Scala:
293+
```scala
294+
object Solution {
295+
def removeNthFromEnd(head: ListNode, n: Int): ListNode = {
296+
val dummy = new ListNode(-1, head) // 定义虚拟头节点
297+
var fast = head // 快指针从头开始走
298+
var slow = dummy // 慢指针从虚拟头开始头
299+
// 因为参数 n 是不可变量,所以不能使用 while(n>0){n-=1}的方式
300+
for (i <- 0 until n) {
301+
fast = fast.next
302+
}
303+
// 快指针和满指针一起走,直到fast走到null
304+
while (fast != null) {
305+
slow = slow.next
306+
fast = fast.next
307+
}
308+
// 删除slow的下一个节点
309+
slow.next = slow.next.next
310+
// 返回虚拟头节点的下一个
311+
dummy.next
312+
}
313+
}
314+
```
293315
-----------------------
294316
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

‎problems/0024.两两交换链表中的节点.md‎

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,29 @@ func swapPairs(_ head: ListNode?) -> ListNode? {
311311
return dummyHead.next
312312
}
313313
```
314-
314+
Scala:
315+
```scala
316+
// 虚拟头节点
317+
object Solution {
318+
def swapPairs(head: ListNode): ListNode = {
319+
var dummy = new ListNode(0, head) // 虚拟头节点
320+
var pre = dummy
321+
var cur = head
322+
// 当pre的下一个和下下个都不为空,才进行两两转换
323+
while (pre.next != null && pre.next.next != null) {
324+
var tmp: ListNode = cur.next.next // 缓存下一次要进行转换的第一个节点
325+
pre.next = cur.next // 步骤一
326+
cur.next.next = cur // 步骤二
327+
cur.next = tmp // 步骤三
328+
// 下面是准备下一轮的交换
329+
pre = cur
330+
cur = tmp
331+
}
332+
// 最终返回dummy虚拟头节点的下一个,return可以省略
333+
dummy.next
334+
}
335+
}
336+
```
315337

316338
-----------------------
317339
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

‎problems/0027.移除元素.md‎

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public:
8181

8282
**双指针法(快慢指针法)在数组和链表的操作中是非常常见的,很多考察数组、链表、字符串等操作的面试题,都使用双指针法。**
8383

84-
后序都会一一介绍到,本题代码如下:
84+
后续都会一一介绍到,本题代码如下:
8585

8686
```CPP
8787
// 时间复杂度:O(n)
@@ -328,6 +328,20 @@ int removeElement(int* nums, int numsSize, int val){
328328
return slow;
329329
}
330330
```
331-
331+
Scala:
332+
```scala
333+
object Solution {
334+
def removeElement(nums: Array[Int], `val`: Int): Int = {
335+
var slow = 0
336+
for (fast <- 0 until nums.length) {
337+
if (`val` != nums(fast)) {
338+
nums(slow) = nums(fast)
339+
slow += 1
340+
}
341+
}
342+
slow
343+
}
344+
}
345+
```
332346
-----------------------
333347
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

‎problems/0034.在排序数组中查找元素的第一个和最后一个位置.md‎

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,52 @@ var searchRange = function(nums, target) {
480480
return [-1, -1];
481481
};
482482
```
483-
483+
### Scala
484+
```scala
485+
object Solution {
486+
def searchRange(nums: Array[Int], target: Int): Array[Int] = {
487+
var left = getLeftBorder(nums, target)
488+
var right = getRightBorder(nums, target)
489+
if (left == -2 || right == -2) return Array(-1, -1)
490+
if (right - left > 1) return Array(left + 1, right - 1)
491+
Array(-1, -1)
492+
}
493+
494+
// 寻找左边界
495+
def getLeftBorder(nums: Array[Int], target: Int): Int = {
496+
var leftBorder = -2
497+
var left = 0
498+
var right = nums.length - 1
499+
while (left <= right) {
500+
var mid = left + (right - left) / 2
501+
if (nums(mid) >= target) {
502+
right = mid - 1
503+
leftBorder = right
504+
} else {
505+
left = mid + 1
506+
}
507+
}
508+
leftBorder
509+
}
510+
511+
// 寻找右边界
512+
def getRightBorder(nums: Array[Int], target: Int): Int = {
513+
var rightBorder = -2
514+
var left = 0
515+
var right = nums.length - 1
516+
while (left <= right) {
517+
var mid = left + (right - left) / 2
518+
if (nums(mid) <= target) {
519+
left = mid + 1
520+
rightBorder = left
521+
} else {
522+
right = mid - 1
523+
}
524+
}
525+
rightBorder
526+
}
527+
}
528+
```
484529

485530
-----------------------
486531
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

‎problems/0035.搜索插入位置.md‎

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,52 @@ func searchInsert(_ nums: [Int], _ target: Int) -> Int {
316316
return right + 1
317317
}
318318
```
319+
### Scala
320+
```scala
321+
object Solution {
322+
def searchInsert(nums: Array[Int], target: Int): Int = {
323+
var left = 0
324+
var right = nums.length - 1
325+
while (left <= right) {
326+
var mid = left + (right - left) / 2
327+
if (target == nums(mid)) {
328+
return mid
329+
} else if (target > nums(mid)) {
330+
left = mid + 1
331+
} else {
332+
right = mid - 1
333+
}
334+
}
335+
right + 1
336+
}
337+
}
338+
```
319339

320-
340+
### PHP
341+
342+
```php
343+
// 二分法(1):[左闭右闭]
344+
function searchInsert($nums, $target)
345+
{
346+
$n = count($nums);
347+
$l = 0;
348+
$r = $n - 1;
349+
while ($l <= $r) {
350+
$mid = floor(($l + $r) / 2);
351+
if ($nums[$mid] > $target) {
352+
// 下次搜索在左区间:[$l,$mid-1]
353+
$r = $mid - 1;
354+
} else if ($nums[$mid] < $target) {
355+
// 下次搜索在右区间:[$mid+1,$r]
356+
$l = $mid + 1;
357+
} else {
358+
// 命中返回
359+
return $mid;
360+
}
361+
}
362+
return $r + 1;
363+
}
364+
```
321365

322366

323367
-----------------------

‎problems/0039.组合总和.md‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -370,18 +370,17 @@ func backtracking(startIndex,sum,target int,candidates,trcak []int,res *[][]int)
370370
```js
371371
var combinationSum = function(candidates, target) {
372372
const res = [], path = [];
373-
candidates.sort(); // 排序
373+
candidates.sort((a,b)=>a-b); // 排序
374374
backtracking(0, 0);
375375
return res;
376376
function backtracking(j, sum) {
377-
if (sum > target) return;
378377
if (sum === target) {
379378
res.push(Array.from(path));
380379
return;
381380
}
382381
for(let i = j; i < candidates.length; i++ ) {
383382
const n = candidates[i];
384-
if(n > target - sum) continue;
383+
if(n > target - sum) break;
385384
path.push(n);
386385
sum += n;
387386
backtracking(i, sum);

‎problems/0040.组合总和II.md‎

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -508,22 +508,27 @@ func backtracking(startIndex,sum,target int,candidates,trcak []int,res *[][]int)
508508
*/
509509
var combinationSum2 = function(candidates, target) {
510510
const res = []; path = [], len = candidates.length;
511-
candidates.sort();
511+
candidates.sort((a,b)=>a-b);
512512
backtracking(0, 0);
513513
return res;
514514
function backtracking(sum, i) {
515-
if (sum > target) return;
516515
if (sum === target) {
517516
res.push(Array.from(path));
518517
return;
519518
}
520-
let f = -1;
521519
for(let j = i; j < len; j++) {
522520
const n = candidates[j];
523-
if(n > target - sum || n === f) continue;
521+
if(j > i && candidates[j] === candidates[j-1]){
522+
//若当前元素和前一个元素相等
523+
//则本次循环结束,防止出现重复组合
524+
continue;
525+
}
526+
//如果当前元素值大于目标值-总和的值
527+
//由于数组已排序,那么该元素之后的元素必定不满足条件
528+
//直接终止当前层的递归
529+
if(n > target - sum) break;
524530
path.push(n);
525531
sum += n;
526-
f = n;
527532
backtracking(sum, j + 1);
528533
path.pop();
529534
sum -= n;

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /