├── .gitignore ├── 1-100 ├── 1.md ├── 10.md ├── 11.md ├── 12.md ├── 13.md ├── 14.md ├── 15.md ├── 16.md ├── 17.md ├── 18.md ├── 19.md ├── 2.md ├── 20.md ├── 21.md ├── 22.md ├── 23.md ├── 24.md ├── 25.md ├── 26.md ├── 27.md ├── 28.md ├── 29.md ├── 3.md ├── 30.md ├── 31.md ├── 32.md ├── 33.md ├── 34.md ├── 35.md ├── 36.md ├── 37.md ├── 38.md ├── 39.md ├── 4.md ├── 40.md ├── 41.md ├── 42.md ├── 43.md ├── 44.md ├── 45.md ├── 46.md ├── 47.md ├── 48.md ├── 49.md ├── 5.md ├── 50.md ├── 51.md ├── 52.md ├── 53.md ├── 54.md ├── 55.md ├── 56.md ├── 57.md ├── 58.md ├── 59.md ├── 6.md ├── 60.md ├── 61.md ├── 62.md ├── 63.md ├── 64.md ├── 65.md ├── 66.md ├── 67.md ├── 68.md ├── 69.md ├── 7.md ├── 70.md ├── 71.md ├── 72.md ├── 73.md ├── 74.md ├── 75.md ├── 76.md ├── 77.md ├── 78.md ├── 79.md ├── 8.md ├── 80.md ├── 81.md ├── 82.md ├── 83.md ├── 84.md ├── 85.md ├── 86.md ├── 87.md ├── 88.md ├── 89.md ├── 9.md ├── 90.md ├── 91.md ├── 92.md ├── 93.md ├── 94.md ├── 95.md ├── 96.md ├── 97.md ├── 98.md └── 99.md ├── 1001-1100 ├── 1000.md ├── 1001.md ├── 1002.md ├── 1003.md ├── 1004.md ├── 1005.md ├── 1006.md ├── 1007.md ├── 1008.md ├── 1009.md ├── 1010.md ├── 1011.md ├── 1012.md ├── 1013.md ├── 1014.md ├── 1015.md ├── 1016.md ├── 1017.md ├── 1018.md ├── 1019.md ├── 1020.md ├── 1021.md ├── 1022.md ├── 1023.md ├── 1024.md ├── 1025.md ├── 1026.md ├── 1027.md ├── 1028.md ├── 1029.md ├── 1030.md ├── 1031.md ├── 1032.md ├── 1033.md ├── 1034.md ├── 1035.md ├── 1036.md ├── 1037.md ├── 1038.md ├── 1039.md ├── 1040.md ├── 1041.md ├── 1042.md ├── 1043.md ├── 1044.md ├── 1046.md ├── 1047.md ├── 1048.md └── 1049.md ├── 101-200 ├── 100.md ├── 101.md ├── 102.md ├── 103.md ├── 104.md ├── 105.md ├── 106.md ├── 107.md ├── 108.md ├── 109.md ├── 110.md ├── 111.md ├── 112.md ├── 113.md ├── 114.md ├── 115.md ├── 116.md ├── 117.md ├── 118.md ├── 119.md ├── 120.md ├── 121.md ├── 122.md ├── 123.md ├── 124.md ├── 125.md ├── 126.md ├── 127.md ├── 128.md ├── 129.md ├── 130.md ├── 131.md ├── 132.md ├── 133.md ├── 134.md ├── 135.md ├── 136.md ├── 137.md ├── 138.md ├── 139.md ├── 140.md ├── 141.md ├── 142.md ├── 143.md ├── 144.md ├── 145.md ├── 146.md ├── 147.md ├── 148.md ├── 149.md ├── 150.md ├── 151.md ├── 152.md ├── 153.md ├── 154.md ├── 155.md ├── 160.md ├── 162.md ├── 164.md ├── 165.md ├── 166.md ├── 167.md ├── 168.md ├── 169.md ├── 171.md ├── 172.md ├── 173.md ├── 174.md ├── 179.md ├── 187.md ├── 188.md ├── 189.md ├── 190.md ├── 191.md ├── 198.md └── 199.md ├── 201-300 ├── 200.md ├── 201.md ├── 202.md ├── 203.md ├── 204.md ├── 205.md ├── 206.md ├── 207.md ├── 208.md ├── 209.md ├── 210.md ├── 211.md ├── 212.md ├── 213.md ├── 214.md ├── 215.md ├── 216.md ├── 217.md ├── 218.md ├── 219.md ├── 220.md ├── 221.md ├── 222.md ├── 223.md ├── 224.md ├── 225.md ├── 226.md ├── 227.md ├── 228.md ├── 229.md ├── 230.md ├── 231.md ├── 232.md ├── 233.md ├── 234.md ├── 235.md ├── 236.md ├── 237.md ├── 238.md ├── 239.md ├── 240.md ├── 241.md ├── 242.md ├── 257.md ├── 258.md ├── 260.md ├── 263.md ├── 264.md ├── 268.md ├── 273.md ├── 274.md ├── 275.md ├── 278.md ├── 279.md ├── 282.md ├── 283.md ├── 287.md ├── 289.md ├── 290.md ├── 292.md ├── 295.md ├── 297.md └── 299.md ├── 301-400 ├── 300.md ├── 301.md ├── 303.md ├── 304.md ├── 306.md ├── 307.md ├── 309.md ├── 310.md ├── 312.md ├── 313.md ├── 315.md ├── 316.md ├── 318.md ├── 319.md ├── 321.md ├── 322.md ├── 324.md ├── 326.md ├── 327.md ├── 328.md ├── 329.md ├── 330.md ├── 331.md ├── 332.md ├── 334.md ├── 335.md ├── 336.md ├── 337.md ├── 338.md ├── 341.md ├── 342.md ├── 343.md ├── 344.md ├── 345.md ├── 347.md ├── 349.md ├── 350.md ├── 352.md ├── 354.md ├── 355.md ├── 357.md ├── 363.md ├── 365.md ├── 367.md ├── 368.md ├── 371.md ├── 372.md ├── 373.md ├── 375.md ├── 376.md ├── 377.md ├── 378.md ├── 380.md ├── 381.md ├── 382.md ├── 383.md ├── 384.md ├── 385.md ├── 386.md ├── 387.md ├── 388.md ├── 389.md ├── 390.md ├── 391.md ├── 392.md ├── 393.md ├── 394.md ├── 395.md ├── 396.md ├── 397.md ├── 398.md └── 399.md ├── 401-500 ├── 400.md ├── 401.md ├── 402.md ├── 403.md ├── 404.md ├── 405.md ├── 406.md ├── 407.md ├── 409.md ├── 410.md ├── 412.md ├── 413.md ├── 414.md ├── 415.md ├── 416.md ├── 417.md ├── 419.md ├── 420.md ├── 421.md ├── 423.md ├── 424.md ├── 427.md ├── 429.md ├── 430.md ├── 432.md ├── 433.md ├── 434.md ├── 435.md ├── 436.md ├── 437.md ├── 438.md ├── 440.md ├── 441.md ├── 442.md ├── 443.md ├── 445.md ├── 446.md ├── 447.md ├── 448.md ├── 449.md ├── 450.md ├── 451.md ├── 452.md ├── 453.md ├── 454.md ├── 455.md ├── 456.md ├── 457.md ├── 458.md ├── 459.md ├── 460.md ├── 461.md ├── 462.md ├── 463.md ├── 464.md ├── 466.md ├── 467.md ├── 468.md ├── 470.md ├── 472.md ├── 473.md ├── 474.md ├── 475.md ├── 476.md ├── 477.md ├── 478.md ├── 479.md ├── 480.md ├── 481.md ├── 482.md ├── 483.md ├── 485.md ├── 486.md ├── 488.md ├── 491.md ├── 492.md ├── 493.md ├── 494.md ├── 495.md ├── 496.md ├── 497.md └── 498.md ├── 501-600 ├── 500.md ├── 501.md ├── 502.md ├── 503.md ├── 504.md ├── 506.md ├── 507.md ├── 508.md ├── 509.md ├── 513.md ├── 514.md ├── 515.md ├── 516.md ├── 517.md ├── 518.md ├── 519.md ├── 520.md ├── 521.md ├── 522.md ├── 523.md ├── 524.md ├── 525.md ├── 526.md ├── 528.md ├── 529.md ├── 530.md ├── 532.md ├── 535.md ├── 537.md ├── 538.md ├── 539.md ├── 540.md ├── 541.md ├── 542.md ├── 543.md ├── 546.md ├── 547.md ├── 551.md ├── 552.md ├── 553.md ├── 554.md ├── 556.md ├── 557.md ├── 558.md ├── 559.md ├── 560.md ├── 561.md ├── 563.md ├── 564.md ├── 565.md ├── 566.md ├── 567.md ├── 572.md ├── 575.md ├── 576.md ├── 581.md ├── 583.md ├── 587.md ├── 589.md ├── 590.md ├── 591.md ├── 592.md ├── 593.md ├── 594.md ├── 598.md └── 599.md ├── 601-700 ├── 600.md ├── 605.md ├── 606.md ├── 609.md ├── 611.md ├── 617.md ├── 621.md ├── 622.md ├── 623.md ├── 628.md ├── 629.md ├── 630.md ├── 632.md ├── 633.md ├── 636.md ├── 637.md ├── 638.md ├── 639.md ├── 640.md ├── 641.md ├── 643.md ├── 645.md ├── 646.md ├── 647.md ├── 648.md ├── 649.md ├── 650.md ├── 652.md ├── 653.md ├── 654.md ├── 655.md ├── 657.md ├── 658.md ├── 659.md ├── 661.md ├── 662.md ├── 664.md ├── 665.md ├── 667.md ├── 668.md ├── 669.md ├── 670.md ├── 671.md ├── 672.md ├── 673.md ├── 674.md ├── 675.md ├── 676.md ├── 677.md ├── 678.md ├── 679.md ├── 680.md ├── 682.md ├── 684.md ├── 685.md ├── 686.md ├── 687.md ├── 688.md ├── 689.md ├── 691.md ├── 692.md ├── 693.md ├── 695.md ├── 696.md ├── 697.md ├── 698.md └── 699.md ├── 701-800 ├── 700.md ├── 701.md ├── 703.md ├── 704.md ├── 705.md ├── 706.md ├── 707.md ├── 709.md ├── 710.md ├── 712.md ├── 713.md ├── 714.md ├── 715.md ├── 717.md ├── 718.md ├── 719.md ├── 720.md ├── 721.md ├── 722.md ├── 724.md ├── 725.md ├── 726.md ├── 728.md ├── 729.md ├── 730.md ├── 731.md ├── 732.md ├── 733.md ├── 735.md ├── 736.md ├── 738.md ├── 739.md ├── 740.md ├── 741.md ├── 743.md ├── 744.md ├── 745.md ├── 746.md ├── 747.md ├── 748.md ├── 749.md ├── 752.md ├── 753.md ├── 754.md ├── 756.md ├── 757.md ├── 761.md ├── 762.md ├── 763.md ├── 764.md ├── 765.md ├── 766.md ├── 767.md ├── 768.md ├── 769.md ├── 770.md ├── 771.md ├── 773.md ├── 775.md ├── 777.md ├── 778.md ├── 779.md ├── 780.md ├── 781.md ├── 782.md ├── 783.md ├── 784.md ├── 785.md ├── 786.md ├── 787.md ├── 788.md ├── 789.md ├── 790.md ├── 791.md ├── 792.md ├── 793.md ├── 794.md ├── 795.md ├── 796.md ├── 797.md ├── 798.md └── 799.md ├── 801-900 ├── 801.md ├── 802.md ├── 803.md ├── 804.md ├── 805.md ├── 806.md ├── 807.md ├── 808.md ├── 809.md ├── 810.md ├── 811.md ├── 812.md ├── 813.md ├── 814.md ├── 815.md ├── 816.md ├── 817.md ├── 818.md ├── 819.md ├── 820.md ├── 821.md ├── 822.md ├── 823.md ├── 824.md ├── 825.md ├── 826.md ├── 827.md ├── 828.md ├── 829.md ├── 830.md ├── 831.md ├── 832.md ├── 833.md ├── 834.md ├── 835.md ├── 836.md ├── 837.md ├── 838.md ├── 839.md ├── 840.md ├── 841.md ├── 842.md ├── 843.md ├── 844.md ├── 845.md ├── 846.md ├── 847.md ├── 848.md ├── 849.md ├── 850.md ├── 851.md ├── 852.md ├── 853.md ├── 854.md ├── 855.md ├── 856.md ├── 857.md ├── 858.md ├── 859.md ├── 860.md ├── 861.md ├── 862.md ├── 863.md ├── 864.md ├── 865.md ├── 866.md ├── 867.md ├── 868.md ├── 869.md ├── 870.md ├── 871.md ├── 872.md ├── 873.md ├── 874.md ├── 875.md ├── 876.md ├── 877.md ├── 878.md ├── 879.md ├── 880.md ├── 881.md ├── 882.md ├── 883.md ├── 884.md ├── 885.md ├── 886.md ├── 887.md ├── 888.md ├── 889.md ├── 890.md ├── 891.md ├── 892.md ├── 893.md ├── 894.md ├── 895.md ├── 896.md ├── 897.md ├── 898.md └── 899.md ├── 901-1000 ├── 900.md ├── 901.md ├── 902.md ├── 903.md ├── 904.md ├── 905.md ├── 906.md ├── 907.md ├── 908.md ├── 909.md ├── 910.md ├── 911.md ├── 912.md ├── 913.md ├── 914.md ├── 915.md ├── 916.md ├── 917.md ├── 918.md ├── 919.md ├── 920.md ├── 921.md ├── 922.md ├── 923.md ├── 924.md ├── 925.md ├── 926.md ├── 927.md ├── 928.md ├── 929.md ├── 930.md ├── 931.md ├── 932.md ├── 933.md ├── 934.md ├── 935.md ├── 936.md ├── 937.md ├── 938.md ├── 939.md ├── 940.md ├── 941.md ├── 942.md ├── 943.md ├── 944.md ├── 945.md ├── 946.md ├── 947.md ├── 948.md ├── 949.md ├── 950.md ├── 951.md ├── 952.md ├── 953.md ├── 954.md ├── 955.md ├── 956.md ├── 957.md ├── 958.md ├── 959.md ├── 960.md ├── 961.md ├── 962.md ├── 963.md ├── 964.md ├── 965.md ├── 966.md ├── 967.md ├── 968.md ├── 969.md ├── 970.md ├── 971.md ├── 972.md ├── 973.md ├── 974.md ├── 975.md ├── 976.md ├── 977.md ├── 978.md ├── 979.md ├── 980.md ├── 981.md ├── 982.md ├── 983.md ├── 984.md ├── 985.md ├── 986.md ├── 987.md ├── 988.md ├── 989.md ├── 990.md ├── 991.md ├── 992.md ├── 993.md ├── 994.md ├── 995.md ├── 996.md ├── 997.md ├── 998.md └── 999.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | -------------------------------------------------------------------------------- /1-100/1.md: -------------------------------------------------------------------------------- 1 | ### 1. 两数之和 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`数组`、`哈希表` 6 | 7 | 给定一个整数数组 `nums` 和一个目标值 `target` ,请你在该数组中找出和为目标值的那**两个** 整数,并返回他们的数组下标。 8 | 9 | 10 | 11 | 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 12 | 13 | 14 | 15 | **示例:** 16 | 17 | 18 | 19 | ``` 20 | 给定 nums = [2, 7, 11, 15], target = 9 21 | 22 | 因为 nums[0] + nums[1] = 2 + 7 = 9 23 | 所以返回 [0, 1] 24 | ``` 25 | 26 | ``` 27 | /** 28 | * @param {number[]} nums 29 | * @param {number} target 30 | * @return {number[]} 31 | */ 32 | var twoSum = function(nums, target) { 33 | let hash={} 34 | for(let i=0;ia-b) 36 | let result=null 37 | let min=Infinity 38 | for(let fix=0;fixtarget)right-- 49 | else left++ 50 | } 51 | } 52 | return result 53 | }; 54 | ``` 55 | 56 | -------------------------------------------------------------------------------- /1-100/21.md: -------------------------------------------------------------------------------- 1 | ### 21. 合并两个有序链表 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`链表` 6 | 7 | 将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 8 | 9 | 10 | 11 | **示例:** 12 | 13 | 14 | 15 | ``` 16 | 输入:1->2->4, 1->3->4 17 | 输出:1->1->2->3->4->4 18 | ``` 19 | 20 | ``` 21 | /** 22 | * Definition for singly-linked list. 23 | * function ListNode(val) { 24 | * this.val = val; 25 | * this.next = null; 26 | * } 27 | */ 28 | /** 29 | * @param {ListNode} l1 30 | * @param {ListNode} l2 31 | * @return {ListNode} 32 | */ 33 | var mergeTwoLists = function(l1, l2) { 34 | if(l1==null)return l2 35 | if(l2==null)return l1 36 | if(l1.valn || lNn`(`n`为当前数组的长度),不处理,因此如果存在以上的数字,那么最最终结果一定在`[1,n]`之间。 55 | 56 | 因此,只需要对`[1,n]`内部的数字放到对应的`num-1`索引上,例如`1`就应该放到索引`0`上。 57 | 58 | 通过交换将数字都放好后,对数字遍历查询,如果找到中间某个数字不连续`A[i]!==i+1`,那么就是结果,如果不能存在不连续的数字,返回`n`。 59 | 60 | ``` 61 | /** 62 | * @param {number[]} nums 63 | * @return {number} 64 | */ 65 | var firstMissingPositive = function(A) { 66 | let n=A.length 67 | for(let i=0;i0 && A[i]<=n && A[A[i] - 1]!==A[i]){ 69 | swap(i, A[i]-1) 70 | } 71 | } 72 | for(let i=0;i= nums.length-1 59 | }; 60 | ``` 61 | 62 | -------------------------------------------------------------------------------- /1-100/56.md: -------------------------------------------------------------------------------- 1 | ### 56. 合并区间 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`排序`、`数组` 6 | 7 | 给出一个区间的集合,请合并所有重叠的区间。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | 14 | 15 | ``` 16 | 输入: [[1,3],[2,6],[8,10],[15,18]] 17 | 输出: [[1,6],[8,10],[15,18]] 18 | 解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6]. 19 | ``` 20 | 21 | 22 | **示例2:** 23 | 24 | 25 | 26 | ``` 27 | 输入: [[1,4],[4,5]] 28 | 输出: [[1,5]] 29 | 解释: 区间 [1,4] 和 [4,5] 可被视为重叠区间。 30 | ``` 31 | 32 | 33 | 34 | ----- 35 | 36 | 思路: 37 | 38 | 定义一个新数组`result`,用于存放更新后的所有区间。 39 | 40 | 先按照起点排序,如果当前区间的起点和上一个区间的终点存在交集,则更新上一个区间终点的位置为当前区间终点的位置; 41 | 42 | 否则,直接`push`当前区间。 43 | 44 | ``` 45 | /** 46 | * @param {number[][]} intervals 47 | * @return {number[][]} 48 | */ 49 | var merge = function(intervals) { 50 | intervals.sort((a,b)=>a[0]===b[0]?a[1]-b[1]:a[0]-b[0]) 51 | let result=[] 52 | for(let [x,y] of intervals){ 53 | if(result.length===0){ 54 | result.push([x,y]) 55 | }else{ 56 | let last=result[result.length-1] 57 | if(x>last[1]){ 58 | result.push([x,y]) 59 | }else{ 60 | last[1]=Math.max(last[1],y) 61 | } 62 | } 63 | } 64 | return result 65 | }; 66 | ``` 67 | 68 | -------------------------------------------------------------------------------- /1-100/58.md: -------------------------------------------------------------------------------- 1 | ### 58. 最后一个单词的长度 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`字符串` 6 | 7 | 给定一个仅包含大小写字母和空格 `' '` 的字符串,返回其最后一个单词的长度。 8 | 9 | 10 | 11 | 如果不存在最后一个单词,请返回 0。 12 | 13 | 14 | 15 | **说明:** 一个单词是指由字母组成,但不包含任何空格的字符串。 16 | 17 | 18 | 19 | **示例:** 20 | 21 | 22 | 23 | ``` 24 | 输入: "Hello World" 25 | 输出: 5 26 | ``` 27 | 28 | 29 | 30 | ----- 31 | 32 | 思路: 33 | 34 | 倒序遍历,当还未碰到任何字母时,跳过空格,如果已经存在字母,遇到空格则`break`。 35 | 36 | ``` 37 | /** 38 | * @param {string} s 39 | * @return {number} 40 | */ 41 | var lengthOfLastWord = function(s) { 42 | let len=0 43 | for(let i=s.length-1;i>=0;i--){ 44 | if(len===0 && s[i]===' ')continue 45 | if(s[i]===' ')break 46 | len++ 47 | } 48 | return len 49 | }; 50 | ``` 51 | 52 | -------------------------------------------------------------------------------- /1-100/59.md: -------------------------------------------------------------------------------- 1 | ### 59. 螺旋矩阵 II 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`数组` 6 | 7 | 给定一个正整数*n* ,生成一个包含 1 到*n* 2所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。 8 | 9 | 10 | 11 | **示例:** 12 | 13 | 14 | 15 | ``` 16 | 输入: 3 17 | 输出: 18 | [ 19 | [ 1, 2, 3 ], 20 | [ 8, 9, 4 ], 21 | [ 7, 6, 5 ] 22 | ] 23 | ``` 24 | 25 | 26 | 27 | ----- 28 | 29 | 思路: 30 | 31 | 与`NO.54`差不多,一层一层地处理添加到`result`中。 32 | 33 | ``` 34 | /** 35 | * @param {number} n 36 | * @return {number[][]} 37 | */ 38 | var generateMatrix = function(n) { 39 | let start=0,end=n-1,num=1 40 | let result=[] 41 | for(let i=0;i=start){ 45 | let i=start 46 | while(i<=end)result[start][i++]=num++ 47 | i=start+1 48 | while(i<=end)result[i++][end]=num++ 49 | i=end-1 50 | while(i>=start)result[end][i--]=num++ 51 | i=end-1 52 | while(i>=start+1)result[i--][start]=num++ 53 | start++;end-- 54 | } 55 | return result 56 | }; 57 | ``` 58 | 59 | -------------------------------------------------------------------------------- /1-100/64.md: -------------------------------------------------------------------------------- 1 | ### 64. 最小路径和 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`数组`、`动态规划` 6 | 7 | 给定一个包含非负整数的 *m* x*n* 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。 8 | 9 | 10 | 11 | **说明:** 每次只能向下或者向右移动一步。 12 | 13 | 14 | 15 | **示例:** 16 | 17 | 18 | 19 | ``` 20 | 输入: 21 | [ 22 | [1,3,1], 23 | [1,5,1], 24 | [4,2,1] 25 | ] 26 | 输出: 7 27 | 解释: 因为路径 1→3→1→1→1 的总和最小。 28 | ``` 29 | 30 | 31 | 32 | ----- 33 | 34 | 思路: 35 | 36 | 与`NO.62`和`NO.63`一个模式。 37 | 38 | `dp[i][j]`代表当前位置的最小路径和,状态转移方程: 39 | 40 | 右侧:`dp[i+1][j]=Math.min(dp[i+1][j],dp[i][j]+grid[i+1][j])` 41 | 42 | 下侧:`dp[i][j+1]=Math.min(dp[i][j+1],dp[i][j]+grid[i][j+1])` 43 | 44 | ``` 45 | /** 46 | * @param {number[][]} grid 47 | * @return {number} 48 | */ 49 | var minPathSum = function(grid) { 50 | if(grid.length===0)return 0 51 | let m=grid.length,n=grid[0].length 52 | let dp=Array(m).fill().map(()=>Array(n).fill(Infinity)) 53 | dp[0][0]=grid[0][0] 54 | for(let i=0;i0 && id>=0){ 56 | digits[id]+=carry 57 | carry=Math.floor(digits[id]/10) 58 | digits[id] %= 10 59 | id-- 60 | } 61 | if(carry>0)digits.unshift(carry) 62 | return digits 63 | 64 | // let i=digits.length-1 65 | // digits[i]+=1 66 | // while(digits[i]===10){ 67 | // digits[i]=0 68 | // if(i===0)digits.unshift(0) 69 | // else i-- 70 | // digits[i]+=1 71 | // } 72 | // return digits 73 | }; 74 | ``` 75 | 76 | -------------------------------------------------------------------------------- /1-100/67.md: -------------------------------------------------------------------------------- 1 | ### 67. 二进制求和 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`数学`、`字符串` 6 | 7 | 给定两个二进制字符串,返回他们的和(用二进制表示)。 8 | 9 | 10 | 11 | 输入为**非空** 字符串且只包含数字 `1` 和 `0` 。 12 | 13 | 14 | 15 | **示例1:** 16 | 17 | 18 | 19 | ``` 20 | 输入: a = "11", b = "1" 21 | 输出: "100" 22 | ``` 23 | 24 | 25 | **示例2:** 26 | 27 | 28 | 29 | ``` 30 | 输入: a = "1010", b = "1011" 31 | 输出: "10101" 32 | ``` 33 | 34 | 35 | 36 | ----- 37 | 38 | 思路: 39 | 40 | 字符串加法的原理,只是`10`进制转为`2`进制。 41 | 42 | ``` 43 | /** 44 | * @param {string} a 45 | * @param {string} b 46 | * @return {string} 47 | */ 48 | var addBinary = function(a, b) { 49 | let res='',carry=0 50 | let i=a.length-1,j=b.length-1 51 | while(i>=0 || j>=0){ 52 | let sum 53 | if(i===-1){ 54 | sum=+b[j--]+carry 55 | }else if(j===-1){ 56 | sum=+a[i--]+carry 57 | }else{ 58 | sum=+a[i--] + +b[j--] +carry 59 | } 60 | carry=Math.floor(sum/2) 61 | sum %=2 62 | res=sum+''+res 63 | } 64 | if(carry>0)return carry+''+res 65 | return res 66 | }; 67 | ``` 68 | 69 | -------------------------------------------------------------------------------- /1-100/69.md: -------------------------------------------------------------------------------- 1 | ### 69. x 的平方根 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`数学`、`二分查找` 6 | 7 | 实现 `int sqrt(int x)` 函数。 8 | 9 | 10 | 11 | 计算并返回*x* 的平方根,其中*x* 是非负整数。 12 | 13 | 14 | 15 | 由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。 16 | 17 | 18 | 19 | **示例 1:** 20 | 21 | 22 | 23 | ``` 24 | 输入: 4 25 | 输出: 2 26 | ``` 27 | 28 | 29 | **示例 2:** 30 | 31 | 32 | 33 | ``` 34 | 输入: 8 35 | 输出: 2 36 | 说明: 8 的平方根是 2.82842..., 37 | 由于返回类型是整数,小数部分将被舍去。 38 | ``` 39 | 40 | 41 | 42 | ----- 43 | 44 | 思路: 45 | 46 | `二分法`,初始最小值`l`为`0`,初始最大值`h`为`Math.floor(x/2)`。 47 | 48 | ``` 49 | /** 50 | * @param {number} x 51 | * @return {number} 52 | */ 53 | var mySqrt = function(x) { 54 | if(x===1)return 1 55 | let l=0,h=Math.floor(x/2) 56 | while(lx)h=mid-1 59 | else l=mid 60 | } 61 | return l 62 | }; 63 | ``` 64 | 65 | -------------------------------------------------------------------------------- /1-100/7.md: -------------------------------------------------------------------------------- 1 | ### 7. 整数反转 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`数学` 6 | 7 | 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。 8 | 9 | 10 | 11 | **示例1:** 12 | 13 | 14 | 15 | ``` 16 | 输入: 123 17 | 输出: 321 18 | ``` 19 | 20 | 21 | **示例 2:** 22 | 23 | 24 | 25 | ``` 26 | 输入: -123 27 | 输出: -321 28 | ``` 29 | 30 | 31 | **示例 3:** 32 | 33 | 34 | 35 | ``` 36 | 输入: 120 37 | 输出: 21 38 | ``` 39 | 40 | 41 | **注意:** 42 | 43 | 44 | 45 | 假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为[−231, 231− 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。 46 | 47 | 48 | 49 | 50 | ----- 51 | 52 | 思路: 53 | 54 | 使用字符串在反转并不是最好的选择,因为还需要处理负号和`0`的情况,用数字运算方式反转比较适合。 55 | 56 | 每次找到当前数的最后一位,然后作为反转数字的第一位,例如`123`: 57 | 58 | ``` 59 | 123 --> 0*10 + 3 60 | 12 --> 3*10 + 2 61 | 1 --> 32*10 + 1 62 | ``` 63 | 64 | 再注意保存开始的正负状态和结果的限制`[−2^31, 2^31 − 1]`。 65 | 66 | ``` 67 | /** 68 | * @param {number} x 69 | * @return {number} 70 | */ 71 | var reverse = function(x) { 72 | let symbol=x<0 ? -1 : 1 73 | x=Math.abs(x) 74 | let res=0 75 | while(x>0){ 76 | let t=x%10 77 | res=res*10+t 78 | x=Math.floor(x/10) 79 | } 80 | res*=symbol 81 | if(res<-Math.pow(2,31) || res>Math.pow(2,31)-1)return 0 82 | return res 83 | }; 84 | ``` 85 | 86 | -------------------------------------------------------------------------------- /1-100/70.md: -------------------------------------------------------------------------------- 1 | ### 70. 爬楼梯 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`动态规划` 6 | 7 | 假设你正在爬楼梯。需要 *n* 阶你才能到达楼顶。 8 | 9 | 10 | 11 | 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? 12 | 13 | 14 | 15 | **注意:** 给定 *n* 是一个正整数。 16 | 17 | 18 | 19 | **示例 1:** 20 | 21 | 22 | 23 | ``` 24 | 输入: 2 25 | 输出: 2 26 | 解释: 有两种方法可以爬到楼顶。 27 | 1. 1 阶 + 1 阶 28 | 2. 2 阶 29 | ``` 30 | 31 | 32 | **示例 2:** 33 | 34 | 35 | 36 | ``` 37 | 输入: 3 38 | 输出: 3 39 | 解释: 有三种方法可以爬到楼顶。 40 | 1. 1 阶 + 1 阶 + 1 阶 41 | 2. 1 阶 + 2 阶 42 | 3. 2 阶 + 1 阶 43 | ``` 44 | 45 | 46 | 47 | ----- 48 | 49 | 思路: 50 | 51 | `DP`,`dp[i]`表示当前楼梯有几种走法,`dp[i]=dp[i-1]+dp[i-2]`。 52 | 53 | ``` 54 | /** 55 | * @param {number} n 56 | * @return {number} 57 | */ 58 | var climbStairs = function(n) { 59 | // let mem=[] 60 | // function getSteps(n){ 61 | // if(mem[n])return mem[n] 62 | // if(n===1)return 1 63 | // if(n===2)return 2 64 | // let steps=getSteps(n-1)+getSteps(n-2) 65 | // mem[n]=steps 66 | // return steps 67 | // } 68 | // return getSteps(n) 69 | let dp=Array(n).fill(0) 70 | dp[0]=1 71 | dp[1]=2 72 | for(let i=2;i1->2 17 | 输出: 1->2 18 | ``` 19 | 20 | 21 | **示例2:** 22 | 23 | 24 | 25 | ``` 26 | 输入: 1->1->2->3->3 27 | 输出: 1->2->3 28 | ``` 29 | 30 | 31 | 32 | ----- 33 | 34 | 思路: 35 | 36 | 只要每次遍历节点时检查下一个节点的`val`和当前节点的`val`是否相等,相等则将`node.next`连接到下一个节点的`next`上(架空下一个节点)。 37 | 38 | ``` 39 | /** 40 | * Definition for singly-linked list. 41 | * function ListNode(val) { 42 | * this.val = val; 43 | * this.next = null; 44 | * } 45 | */ 46 | /** 47 | * @param {ListNode} head 48 | * @return {ListNode} 49 | */ 50 | var deleteDuplicates = function(head) { 51 | if(!head)return head 52 | let node=head 53 | while(node && node.next){ 54 | if(node.next.val===node.val){ 55 | node.next=node.next.next 56 | }else{ 57 | node=node.next 58 | } 59 | } 60 | return head 61 | }; 62 | ``` 63 | 64 | -------------------------------------------------------------------------------- /1-100/86.md: -------------------------------------------------------------------------------- 1 | ### 86. 分隔链表 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`链表`、`双指针` 6 | 7 | 给定一个链表和一个特定值*x* ,对链表进行分隔,使得所有小于 *x* 的节点都在大于或等于 *x* 的节点之前。 8 | 9 | 10 | 11 | 你应当保留两个分区中每个节点的初始相对位置。 12 | 13 | 14 | 15 | **示例:** 16 | 17 | 18 | 19 | ``` 20 | 输入: head = 1->4->3->2->5->2, x = 3 21 | 输出: 1->2->2->4->3->5 22 | ``` 23 | 24 | 25 | 26 | ----- 27 | 28 | 思路: 29 | 30 | 建立一个链表头`less`和链表头`greater`,遍历链表`head`,如果`head.val=x`放入`greater`中。 31 | 32 | 最后合并`less`和`greater`。 33 | 34 | ``` 35 | /** 36 | * Definition for singly-linked list. 37 | * function ListNode(val) { 38 | * this.val = val; 39 | * this.next = null; 40 | * } 41 | */ 42 | /** 43 | * @param {ListNode} head 44 | * @param {number} x 45 | * @return {ListNode} 46 | */ 47 | var partition = function(head, x) { 48 | let node=new ListNode(0),less=node, 49 | node2=new ListNode(0),greater=node2 50 | while(head){ 51 | if(head.val0){ 72 | let t=n%10 73 | rev=rev*10+t 74 | n=~~(n/10) 75 | } 76 | return rev===x 77 | }; 78 | ``` 79 | 80 | -------------------------------------------------------------------------------- /1-100/90.md: -------------------------------------------------------------------------------- 1 | ### 90. 子集 II 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`数组`、`回溯算法` 6 | 7 | 给定一个可能包含重复元素的整数数组 ***nums*** ,返回该数组所有可能的子集(幂集)。 8 | 9 | 10 | 11 | **说明:** 解集不能包含重复的子集。 12 | 13 | 14 | 15 | **示例:** 16 | 17 | 18 | 19 | ``` 20 | 输入: [1,2,2] 21 | 输出: 22 | [ 23 | [2], 24 | [1], 25 | [1,2,2], 26 | [2,2], 27 | [1,2], 28 | [] 29 | ] 30 | ``` 31 | 32 | 33 | 34 | ----- 35 | 36 | 思路: 37 | 38 | 由于输入含有重复值,因此需要排序并且通过`if(i>start && nums[i]===nums[i-1])continue)`去重。 39 | 40 | ``` 41 | /** 42 | * @param {number[]} nums 43 | * @return {number[][]} 44 | */ 45 | var subsetsWithDup = function(nums) { 46 | let result=[],temp=[] 47 | nums.sort() 48 | backtrack(result,0,temp,nums) 49 | return result 50 | function backtrack(result,start,temp,nums){ 51 | result.push(temp.slice()) 52 | for(let i=start;istart && nums[i]===nums[i-1])continue 54 | temp.push(nums[i]) 55 | backtrack(result,i+1,temp,nums) 56 | temp.pop() 57 | } 58 | } 59 | }; 60 | ``` 61 | 62 | -------------------------------------------------------------------------------- /1-100/93.md: -------------------------------------------------------------------------------- 1 | ### 93. 复原IP地址 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`字符串`、`回溯算法` 6 | 7 | 给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。 8 | 9 | 10 | 11 | **示例:** 12 | 13 | 14 | 15 | ``` 16 | 输入: "25525511135" 17 | 输出: ["255.255.11.135", "255.255.111.35"] 18 | ``` 19 | 20 | 21 | 22 | ----- 23 | 24 | 思路: 25 | 26 | `回溯`,注意几个规则: 27 | 28 | 1. 变量`cur`表示当前值,如果这个值`>255`,不成立,同时,如果这个值存在`前导0`,同样不成立。 29 | 30 | 2. 变量`remain`表示还剩下的`IP`值(初始为`4`)。 31 | 32 | 3. 变量`str`表示还剩下的字符串,如果`str.length>remain*3`,不成立,因为每一个`IP`数值不可能超过`3`位。 33 | 34 | ``` 35 | /** 36 | * @param {string} s 37 | * @return {string[]} 38 | */ 39 | var restoreIpAddresses = function(s) { 40 | let result=[] 41 | function backtrack(str,remain,cur,res){ 42 | if(str.length>remain*3)return 43 | if(+cur>255 || (cur.length>1 && cur[0]==="0"))return 44 | if(remain===0)return result.push(res.substring(1)) 45 | for(let i=1;i<=3;i++){ 46 | if(str.length0 && S[i]===stack[stack.length-1]){ 60 | stack.pop() 61 | i++ 62 | } 63 | stack.push(S[i++]) 64 | } 65 | return stack.join('') 66 | }; 67 | ``` 68 | 69 | -------------------------------------------------------------------------------- /101-200/103.md: -------------------------------------------------------------------------------- 1 | ### 103. 二叉树的锯齿形层次遍历 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`栈`、`树`、`广度优先搜索` 6 | 7 | 给定一个二叉树,返回其节点值的锯齿形层次遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。 8 | 9 | 10 | 11 | 例如: 12 | 给定二叉树 `[3,9,20,null,null,15,7]` , 13 | 14 | 15 | 16 | ``` 17 | 3 18 | / \ 19 | 9 20 20 | / \ 21 | 15 7 22 | ``` 23 | 24 | 25 | 返回锯齿形层次遍历如下: 26 | 27 | 28 | 29 | ``` 30 | [ 31 | [3], 32 | [20,9], 33 | [15,7] 34 | ] 35 | ``` 36 | 37 | ``` 38 | /** 39 | * Definition for a binary tree node. 40 | * function TreeNode(val) { 41 | * this.val = val; 42 | * this.left = this.right = null; 43 | * } 44 | */ 45 | /** 46 | * @param {TreeNode} root 47 | * @return {number[][]} 48 | */ 49 | var zigzagLevelOrder = function(root) { 50 | if(!root)return [] 51 | let res=[] 52 | let aux=[root] 53 | let h=0 54 | while(aux.length>0){ 55 | h++ 56 | let len=aux.length 57 | let vals=[] 58 | for(let i=0;iend)return null 46 | let mid=Math.floor((start+end)/2) 47 | let root=new TreeNode(nums[mid]) 48 | root.left=createBalance(start,mid-1) 49 | root.right=createBalance(mid+1,end) 50 | return root 51 | } 52 | return createBalance(0,nums.length-1) 53 | }; 54 | ``` 55 | 56 | -------------------------------------------------------------------------------- /101-200/111.md: -------------------------------------------------------------------------------- 1 | ### 111. 二叉树的最小深度 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`树`、`深度优先搜索`、`广度优先搜索` 6 | 7 | 给定一个二叉树,找出其最小深度。 8 | 9 | 10 | 11 | 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 12 | 13 | 14 | 15 | **说明:** 叶子节点是指没有子节点的节点。 16 | 17 | 18 | 19 | **示例:** 20 | 21 | 22 | 23 | 给定二叉树 `[3,9,20,null,null,15,7]` , 24 | 25 | 26 | 27 | ``` 28 | 3 29 | / \ 30 | 9 20 31 | / \ 32 | 15 7 33 | ``` 34 | 35 | 36 | 返回它的最小深度 2. 37 | 38 | 39 | 40 | 41 | ----- 42 | 43 | 思路: 44 | 45 | 必须是`root`到`leaf`的最小高度,如果当前节点是`leaf`,返回`1`;否则: 46 | 47 | 当前节点存在2个子节点,那么返回`min(leftH,rightH)+1`; 48 | 49 | 当前节点只有1个子节点,那么只能返回`存在的子节点的高度+1`。 50 | 51 | ``` 52 | /** 53 | * Definition for a binary tree node. 54 | * function TreeNode(val) { 55 | * this.val = val; 56 | * this.left = this.right = null; 57 | * } 58 | */ 59 | /** 60 | * @param {TreeNode} root 61 | * @return {number} 62 | */ 63 | var minDepth = function(root) { 64 | if(!root)return 0 65 | let leftH=minDepth(root.left), 66 | rightH=minDepth(root.right) 67 | if(root.left && root.right){ 68 | return Math.min(leftH,rightH)+1 69 | }else if(!root.left){ 70 | return rightH+1 71 | }else if(!root.right){ 72 | return leftH+1 73 | } 74 | }; 75 | ``` 76 | 77 | -------------------------------------------------------------------------------- /101-200/112.md: -------------------------------------------------------------------------------- 1 | ### 112. 路径总和 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`树`、`深度优先搜索` 6 | 7 | 给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。 8 | 9 | 10 | 11 | **说明:** 叶子节点是指没有子节点的节点。 12 | 13 | 14 | 15 | **示例:** 16 | 给定如下二叉树,以及目标和 `sum = 22` , 17 | 18 | 19 | 20 | ``` 21 | 5 22 | / \ 23 | 4 8 24 | / / \ 25 | 11 13 4 26 | / \ \ 27 | 7 2 1 28 | ``` 29 | 30 | 31 | 返回 `true` , 因为存在目标和为 22 的根节点到叶子节点的路径 `5->4->11->2` 。 32 | 33 | 34 | ``` 35 | /** 36 | * Definition for a binary tree node. 37 | * function TreeNode(val) { 38 | * this.val = val; 39 | * this.left = this.right = null; 40 | * } 41 | */ 42 | /** 43 | * @param {TreeNode} root 44 | * @param {number} sum 45 | * @return {boolean} 46 | */ 47 | var hasPathSum = function(root, sum) { 48 | if(!root)return false 49 | let s=sum-root.val 50 | if(s===0 && !root.left && !root.right)return true 51 | return hasPathSum(root.left,s) || hasPathSum(root.right,s) 52 | }; 53 | ``` 54 | 55 | -------------------------------------------------------------------------------- /101-200/118.md: -------------------------------------------------------------------------------- 1 | ### 118. 杨辉三角 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`数组` 6 | 7 | 给定一个非负整数*numRows,* 生成杨辉三角的前*numRows* 行。 8 | 9 | 10 | 11 | ![](https://upload.wikimedia.org/wikipedia/commons/0/0d/PascalTriangleAnimated2.gif) 12 | 13 | 14 | 15 | 16 | 在杨辉三角中,每个数是它左上方和右上方的数的和。 17 | 18 | 19 | 20 | **示例:** 21 | 22 | 23 | 24 | ``` 25 | 输入: 5 26 | 输出: 27 | [ 28 | [1], 29 | [1,1], 30 | [1,2,1], 31 | [1,3,3,1], 32 | [1,4,6,4,1] 33 | ] 34 | ``` 35 | 36 | 37 | 38 | ----- 39 | 40 | 思路: 41 | 42 | 要求输出整个三角形,使用`temp`保留上一层的数组,通过`temp`计算当前层。 43 | 44 | ``` 45 | /** 46 | * @param {number} numRows 47 | * @return {number[][]} 48 | */ 49 | var generate = function(numRows) { 50 | let temp=[] 51 | let result=[] 52 | for(let i=0;i=1; j--) 55 | A[j] =(A[j]||0)+ (A[j-1] || 0); 56 | return A; 57 | }; 58 | ``` 59 | 60 | -------------------------------------------------------------------------------- /101-200/121.md: -------------------------------------------------------------------------------- 1 | ### 121. 买卖股票的最佳时机 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`数组`、`动态规划` 6 | 7 | 给定一个数组,它的第*i* 个元素是一支给定股票第 *i* 天的价格。 8 | 9 | 10 | 11 | 如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。 12 | 13 | 14 | 15 | 注意你不能在买入股票前卖出股票。 16 | 17 | 18 | 19 | **示例 1:** 20 | 21 | 22 | 23 | ``` 24 | 输入: [7,1,5,3,6,4] 25 | 输出: 5 26 | 解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。 27 | 注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。 28 | ``` 29 | 30 | 31 | **示例 2:** 32 | 33 | 34 | 35 | ``` 36 | 输入: [7,6,4,3,1] 37 | 输出: 0 38 | 解释:在这种情况下, 没有交易完成, 所以最大利润为 0。 39 | ``` 40 | 41 | 42 | 43 | ----- 44 | 45 | 思路: 46 | 47 | 对于每一天, 48 | 49 | 最大卖出收益为: 50 | 51 | * 上一次买入的+当前卖出的 52 | * 当前不卖(即上一次卖出的) 53 | 54 | 最大买入收益为: 55 | 56 | * 上一次买入的 57 | * 购买今天的(`-prices[i]`) 58 | 59 | 最后返回`sell`。 60 | 61 | ``` 62 | /** 63 | * @param {number[]} prices 64 | * @return {number} 65 | */ 66 | var maxProfit = function(prices) { 67 | let sell=0,buy=-prices[0],rest=0 68 | for(let i=0;iArray(N).fill(false)) 34 | for(let i=0;ia^b) 53 | }; 54 | ``` 55 | 56 | -------------------------------------------------------------------------------- /101-200/137.md: -------------------------------------------------------------------------------- 1 | ### 137. 只出现一次的数字 II 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`位运算` 6 | 7 | 给定一个**非空** 整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。 8 | 9 | 10 | 11 | **说明:** 12 | 13 | 14 | 15 | 你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗? 16 | 17 | 18 | 19 | **示例 1:** 20 | 21 | 22 | 23 | ``` 24 | 输入: [2,2,3,2] 25 | 输出: 3 26 | ``` 27 | 28 | 29 | **示例2:** 30 | 31 | 32 | 33 | ``` 34 | 输入: [0,1,0,1,0,1,99] 35 | 输出: 99 36 | ``` 37 | 38 | 39 | 40 | ----- 41 | 42 | 思路: 43 | 44 | 对于时间`O(n)`,空间`O(1)`的算法,需要编写一个状态机,当一个数出现`3`次,会抵消。 45 | 46 | 如果单变量使用`^`,只能抵消偶数次数,如果要`3`次抵消,必须要有2个变量同时`^`。 47 | 48 | `a=a^nums[i]` 49 | 50 | `b=b^nums[i]` 51 | 52 | 但仅仅这样两个变量完全一致,无法`3`次抵消。 53 | 54 | 因此还需要使用`~`,`~`的作用是将`0`变为`1`,`1`变为`0`,同时也可以将当前状态逆转。 55 | 56 | `a=(a^nums[i]) ~ b` 57 | 58 | `b=(b^nums[i]) ~ a` 59 | 60 | 例如一个数组`[2,2,2,2,2,2]`,它每次的`a`和`b`输出值为`2,0`,`0,2`,`0,0`,`2,0`,`0,2`,`0,0`,每`3`次置零。 61 | 62 | ``` 63 | /** 64 | * @param {number[]} nums 65 | * @return {number} 66 | */ 67 | var singleNumber = function(nums) { 68 | let a=0,b=0 69 | for(let n of nums){ 70 | a=(a^n) & ~b 71 | b=(b^n) & ~a 72 | } 73 | return a 74 | }; 75 | ``` 76 | 77 | -------------------------------------------------------------------------------- /101-200/144.md: -------------------------------------------------------------------------------- 1 | ### 144. 二叉树的前序遍历 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`栈`、`树` 6 | 7 | 给定一个二叉树,返回它的*前序* 遍历。 8 | 9 | 10 | 11 | **示例:** 12 | 13 | 14 | 15 | ``` 16 | 输入: [1,null,2,3] 17 | 1 18 | \ 19 | 2 20 | / 21 | 3 22 | 23 | 输出: [1,2,3] 24 | ``` 25 | 26 | 27 | **进阶:** 递归算法很简单,你可以通过迭代算法完成吗? 28 | 29 | 30 | ``` 31 | /** 32 | * Definition for a binary tree node. 33 | * function TreeNode(val) { 34 | * this.val = val; 35 | * this.left = this.right = null; 36 | * } 37 | */ 38 | /** 39 | * @param {TreeNode} root 40 | * @return {number[]} 41 | */ 42 | var preorderTraversal = function(root) { 43 | let stack=[],res=[] 44 | let node=root 45 | while(stack.length>0 || node){ 46 | while(node){ 47 | res.push(node.val) 48 | stack.push(node) 49 | node=node.left 50 | } 51 | node=stack.pop() 52 | node=node.right 53 | } 54 | return res 55 | }; 56 | ``` 57 | 58 | -------------------------------------------------------------------------------- /101-200/145.md: -------------------------------------------------------------------------------- 1 | ### 145. 二叉树的后序遍历 2 | 3 | 难度:Hard 4 | 5 | 相关话题:`栈`、`树` 6 | 7 | 给定一个二叉树,返回它的 *后序* 遍历。 8 | 9 | 10 | 11 | **示例:** 12 | 13 | 14 | 15 | ``` 16 | 输入: [1,null,2,3] 17 | 1 18 | \ 19 | 2 20 | / 21 | 3 22 | 23 | 输出: [3,2,1] 24 | ``` 25 | 26 | 27 | **进阶:** 递归算法很简单,你可以通过迭代算法完成吗? 28 | 29 | 30 | ``` 31 | /** 32 | * Definition for a binary tree node. 33 | * function TreeNode(val) { 34 | * this.val = val; 35 | * this.left = this.right = null; 36 | * } 37 | */ 38 | /** 39 | * @param {TreeNode} root 40 | * @return {number[]} 41 | */ 42 | var postorderTraversal = function(root) { 43 | let res=[],stack=[],node=root 44 | while(stack.length>0 || node){ 45 | while(node){ 46 | res.push(node.val) 47 | stack.push(node) 48 | node=node.right 49 | } 50 | node=stack.pop() 51 | node=node.left 52 | } 53 | return res.reverse() 54 | }; 55 | ``` 56 | 57 | -------------------------------------------------------------------------------- /101-200/151.md: -------------------------------------------------------------------------------- 1 | ### 151. 翻转字符串里的单词 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`字符串` 6 | 7 | 给定一个字符串,逐个翻转字符串中的每个单词。 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | **示例 1:** 16 | 17 | 18 | 19 | ``` 20 | 输入: "the sky is blue" 21 | 输出:"blue is sky the" 22 | ``` 23 | 24 | 25 | **示例 2:** 26 | 27 | 28 | 29 | ``` 30 | 输入: " hello world! " 31 | 输出:"world! hello" 32 | 解释:输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。 33 | ``` 34 | 35 | 36 | **示例 3:** 37 | 38 | 39 | 40 | ``` 41 | 输入: "a good example" 42 | 输出:"example good a" 43 | 解释:如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。 44 | ``` 45 | 46 | 47 | 48 | 49 | 50 | 51 | **说明:** 52 | 53 | 54 | 55 | 56 | * 无空格字符构成一个单词。 57 | 58 | * 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。 59 | 60 | * 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | **进阶:** 71 | 72 | 73 | 74 | 请选用 C 语言的用户尝试使用*O* (1) 额外空间复杂度的原地解法。 75 | 76 | 77 | ``` 78 | /** 79 | * @param {string} str 80 | * @returns {string} 81 | */ 82 | var reverseWords = function(str) { 83 | let newS=str.trim() 84 | let sArr=newS.split(/\s+/) 85 | sArr.reverse() 86 | return sArr.join(' ') 87 | }; 88 | ``` 89 | 90 | -------------------------------------------------------------------------------- /101-200/152.md: -------------------------------------------------------------------------------- 1 | ### 152. 乘积最大子序列 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`数组`、`动态规划` 6 | 7 | 给定一个整数数组 `nums` ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数)。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | 14 | 15 | ``` 16 | 输入: [2,3,-2,4] 17 | 输出: 6 18 | 解释:子数组 [2,3] 有最大乘积 6。 19 | ``` 20 | 21 | 22 | **示例 2:** 23 | 24 | 25 | 26 | ``` 27 | 输入: [-2,0,-1] 28 | 输出: 0 29 | 解释:结果不能为 2, 因为 [-2,-1] 不是子数组。 30 | ``` 31 | 32 | ``` 33 | /** 34 | * @param {number[]} nums 35 | * @return {number} 36 | */ 37 | var maxProduct = function(nums) { 38 | let maxProd = nums[0]; 39 | let currentMax = maxProd; 40 | let currentMin = maxProd; 41 | 42 | for (let i = 1; i < nums.length; i++) { 43 | // if we hit a negative number, our max is now min and min is now max 44 | if (nums[i] < 0) { 45 | const temp1 = currentMax; 46 | currentMax = currentMin; 47 | currentMin = temp1; 48 | } 49 | currentMax = Math.max(nums[i], nums[i] * currentMax); 50 | currentMin = Math.min(nums[i], nums[i] * currentMin); 51 | maxProd = Math.max(currentMax, maxProd); 52 | } 53 | 54 | return maxProd; 55 | }; 56 | ``` 57 | 58 | -------------------------------------------------------------------------------- /101-200/153.md: -------------------------------------------------------------------------------- 1 | ### 153. 寻找旋转排序数组中的最小值 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`数组`、`二分查找` 6 | 7 | 假设按照升序排序的数组在预先未知的某个点上进行了旋转。 8 | 9 | 10 | 11 | ( 例如,数组 `[0,1,2,4,5,6,7]` **** 可能变为 `[4,5,6,7,0,1,2]` )。 12 | 13 | 14 | 15 | 请找出其中最小的元素。 16 | 17 | 18 | 19 | 你可以假设数组中不存在重复元素。 20 | 21 | 22 | 23 | **示例 1:** 24 | 25 | 26 | 27 | ``` 28 | 输入: [3,4,5,1,2] 29 | 输出: 1 30 | ``` 31 | 32 | 33 | **示例 2:** 34 | 35 | 36 | 37 | ``` 38 | 输入: [4,5,6,7,0,1,2] 39 | 输出: 0 40 | ``` 41 | 42 | ``` 43 | /** 44 | * @param {number[]} nums 45 | * @return {number} 46 | */ 47 | var findMin = function(nums) { 48 | for(let i=0;i nums[hi]) { 69 | lo = mid + 1; 70 | }else if (nums[mid] < nums[hi]) { 71 | hi = mid; 72 | }else { 73 | hi--; 74 | } 75 | } 76 | return nums[lo]; 77 | }; 78 | ``` 79 | 80 | -------------------------------------------------------------------------------- /101-200/162.md: -------------------------------------------------------------------------------- 1 | ### 162. 寻找峰值 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`数组`、`二分查找` 6 | 7 | 峰值元素是指其值大于左右相邻值的元素。 8 | 9 | 10 | 11 | 给定一个输入数组 `nums` ,其中 `nums[i] ≠ nums[i+1]` ,找到峰值元素并返回其索引。 12 | 13 | 14 | 15 | 数组可能包含多个峰值,在这种情况下,返回任何一个峰值所在位置即可。 16 | 17 | 18 | 19 | 你可以假设 `nums[-1] = nums[n] = -∞` 。 20 | 21 | 22 | 23 | **示例 1:** 24 | 25 | 26 | 27 | ``` 28 | 输入: nums = [1,2,3,1] 29 | 输出: 2 30 | 解释:3 是峰值元素,你的函数应该返回其索引 2。 31 | ``` 32 | 33 | 34 | **示例2:** 35 | 36 | 37 | 38 | ``` 39 | 输入: nums = [1,2,1,3,5,6,4] 40 | 输出: 1 或 5 41 | 解释: 你的函数可以返回索引 1,其峰值元素为 2; 42 | 或者返回索引 5, 其峰值元素为 6。 43 | ``` 44 | 45 | 46 | **说明:** 47 | 48 | 49 | 50 | 你的解法应该是*O* (*logN* )** 时间复杂度的。 51 | 52 | 53 | ``` 54 | /** 55 | * @param {number[]} nums 56 | * @return {number} 57 | */ 58 | var findPeakElement = function(nums) { 59 | 60 | // for(let i=1;icur){ 50 | index=i 51 | index2=helper[cur] 52 | }else{ 53 | index2=i 54 | index=helper[cur] 55 | } 56 | break 57 | } 58 | else helper[target-cur]=i 59 | } 60 | return [index+1,index2+1] 61 | }; 62 | ``` 63 | 64 | -------------------------------------------------------------------------------- /101-200/168.md: -------------------------------------------------------------------------------- 1 | ### 168. Excel表列名称 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`数学` 6 | 7 | 给定一个正整数,返回它在 Excel 表中相对应的列名称。 8 | 9 | 10 | 11 | 例如, 12 | 13 | 14 | 15 | ``` 16 | 1 -> A 17 | 2 -> B 18 | 3 -> C 19 | ... 20 | 26 -> Z 21 | 27 -> AA 22 | 28 -> AB 23 | ... 24 | ``` 25 | 26 | 27 | **示例 1:** 28 | 29 | 30 | 31 | ``` 32 | 输入: 1 33 | 输出: "A" 34 | ``` 35 | 36 | 37 | **示例2:** 38 | 39 | 40 | 41 | ``` 42 | 输入: 28 43 | 输出: "AB" 44 | ``` 45 | 46 | 47 | **示例3:** 48 | 49 | 50 | 51 | ``` 52 | 输入: 701 53 | 输出: "ZY" 54 | ``` 55 | 56 | ``` 57 | /** 58 | * @param {number} n 59 | * @return {string} 60 | */ 61 | var convertToTitle = function(n) { 62 | let S='ABCDEFGHIJKLMNOPQRSTUVWXYZ' 63 | let res='' 64 | while(n>0){ 65 | let mod=(n-1)%26 66 | n=Math.floor((n-1)/26) 67 | res=S[mod]+res 68 | } 69 | return res 70 | }; 71 | ``` 72 | 73 | -------------------------------------------------------------------------------- /101-200/169.md: -------------------------------------------------------------------------------- 1 | ### 169. 求众数 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`位运算`、`数组`、`分治算法` 6 | 7 | 给定一个大小为 *n* 的数组,找到其中的众数。众数是指在数组中出现次数**大于** `⌊ n/2 ⌋` 的元素。 8 | 9 | 10 | 11 | 你可以假设数组是非空的,并且给定的数组总是存在众数。 12 | 13 | 14 | 15 | **示例1:** 16 | 17 | 18 | 19 | ``` 20 | 输入: [3,2,3] 21 | 输出: 3 22 | ``` 23 | 24 | 25 | **示例2:** 26 | 27 | 28 | 29 | ``` 30 | 输入: [2,2,1,1,1,2,2] 31 | 输出: 2 32 | ``` 33 | 34 | ``` 35 | /** 36 | * @param {number[]} nums 37 | * @return {number} 38 | */ 39 | var majorityElement = function(nums) { 40 | let count=0,res=null 41 | for(let i=0;i 1 17 | B -> 2 18 | C -> 3 19 | ... 20 | Z -> 26 21 | AA -> 27 22 | AB -> 28 23 | ... 24 | ``` 25 | 26 | 27 | **示例 1:** 28 | 29 | 30 | 31 | ``` 32 | 输入: "A" 33 | 输出: 1 34 | ``` 35 | 36 | 37 | **示例2:** 38 | 39 | 40 | 41 | ``` 42 | 输入:"AB" 43 | 输出: 28 44 | ``` 45 | 46 | 47 | **示例3:** 48 | 49 | 50 | 51 | ``` 52 | 输入:"ZY" 53 | 输出: 701 54 | ``` 55 | 56 | 57 | **致谢:** 58 | 特别感谢[@ts](http://leetcode.com/discuss/user/ts) 59 | 添加此问题并创建所有测试用例。 60 | 61 | 62 | ``` 63 | /** 64 | * @param {string} s 65 | * @return {number} 66 | */ 67 | var titleToNumber = function(s) { 68 | if(s==='')return 0 69 | return (s.charCodeAt(0)-65+1)*Math.pow(26,s.length-1) + titleToNumber(s.slice(1)) 70 | }; 71 | ``` 72 | 73 | -------------------------------------------------------------------------------- /101-200/172.md: -------------------------------------------------------------------------------- 1 | ### 172. 阶乘后的零 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`数学` 6 | 7 | 给定一个整数 *n* ,返回 *n* ! 结果尾数中零的数量。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | 14 | 15 | ``` 16 | 输入: 3 17 | 输出: 0 18 | 解释:3! = 6, 尾数中没有零。 19 | ``` 20 | 21 | 22 | **示例2:** 23 | 24 | 25 | 26 | ``` 27 | 输入: 5 28 | 输出: 1 29 | 解释:5! = 120, 尾数中有 1 个零. 30 | ``` 31 | 32 | 33 | **说明:** 你算法的时间复杂度应为*O* (log*n* )** 。 34 | 35 | 36 | ``` 37 | /** 38 | * @param {number} n 39 | * @return {number} 40 | */ 41 | var trailingZeroes = function(n) { 42 | let x=5,res=0 43 | while(x<=n){ 44 | res+=Math.floor(n/x) 45 | x*=5 46 | } 47 | return res 48 | }; 49 | ``` 50 | 51 | -------------------------------------------------------------------------------- /101-200/179.md: -------------------------------------------------------------------------------- 1 | ### 179. 最大数 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`排序` 6 | 7 | 给定一组非负整数,重新排列它们的顺序使之组成一个最大的整数。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | 14 | 15 | ``` 16 | 输入: [10,2] 17 | 输出: 210 18 | ``` 19 | 20 | 21 | **示例2:** 22 | 23 | 24 | 25 | ``` 26 | 输入: [3,30,34,5,9] 27 | 输出: 9534330 28 | ``` 29 | 30 | 31 | **说明:** 输出结果可能非常大,所以你需要返回一个字符串而不是整数。 32 | 33 | 34 | 35 | 36 | ----- 37 | 38 | 思路: 39 | 40 | 对于两个数字`a`,`b`,只需要比较它们的字符串相加`a+''+b`,`b+''+a`',并且只能找它们从大到小排序。 41 | 42 | ``` 43 | /** 44 | * @param {number[]} nums 45 | * @return {string} 46 | */ 47 | var largestNumber = function(nums) { 48 | nums.sort((a,b)=>(b+''+a)-(a+''+b)) 49 | let res='' 50 | for(let n of nums) res+=n 51 | if(res==='' || res[0]==="0")return "0" 52 | return res 53 | }; 54 | ``` 55 | 56 | -------------------------------------------------------------------------------- /101-200/187.md: -------------------------------------------------------------------------------- 1 | ### 187. 重复的DNA序列 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`位运算`、`哈希表` 6 | 7 | 所有 DNA 由一系列缩写为 A,C,G 和 T 的核苷酸组成,例如:“ACGAATTCCG”。在研究 DNA 时,识别 DNA 中的重复序列有时会对研究非常有帮助。 8 | 9 | 10 | 11 | 编写一个函数来查找 DNA 分子中所有出现超多一次的10个字母长的序列(子串)。 12 | 13 | 14 | 15 | **示例:** 16 | 17 | 18 | 19 | ``` 20 | 输入: s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT" 21 | 22 | 输出: ["AAAAACCCCC", "CCCCCAAAAA"] 23 | ``` 24 | 25 | 26 | 27 | ----- 28 | 29 | 思路: 30 | 31 | 每`10`个字符就存入`hash`,如果有重复,`hash`对应的`val`就`+1`,最终只返回`hash`中`val`为2的字符串,既重复出现了,也避免重复返回。 32 | 33 | ``` 34 | /** 35 | * @param {string} s 36 | * @return {string[]} 37 | */ 38 | var findRepeatedDnaSequences = function(s) { 39 | let hash={} 40 | let res=[] 41 | for(let i=0;i<=s.length-10;i++){ 42 | let str=s.substring(i,i+10) 43 | if(hash[str]==null){ 44 | hash[str]=1 45 | }else{ 46 | hash[str]++ 47 | } 48 | if(hash[str]===2)res.push(str) 49 | } 50 | return res 51 | }; 52 | ``` 53 | 54 | -------------------------------------------------------------------------------- /101-200/199.md: -------------------------------------------------------------------------------- 1 | ### 199. 二叉树的右视图 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`树`、`深度优先搜索`、`广度优先搜索` 6 | 7 | 给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。 8 | 9 | 10 | 11 | **示例:** 12 | 13 | 14 | 15 | ``` 16 | 输入:[1,2,3,null,5,null,4] 17 | 输出:[1, 3, 4] 18 | 解释: 19 | 1 <--- 20 | / \ 21 | 2 3 <--- 22 | \ \ 23 | 5 4 <--- 24 | ``` 25 | 26 | ``` 27 | /** 28 | * Definition for a binary tree node. 29 | * function TreeNode(val) { 30 | * this.val = val; 31 | * this.left = this.right = null; 32 | * } 33 | */ 34 | /** 35 | * @param {TreeNode} root 36 | * @return {number[]} 37 | */ 38 | var rightSideView = function(root) { 39 | if(!root)return [] 40 | let arr=[root] 41 | let res=[] 42 | while(arr.length>0){ 43 | let len=arr.length 44 | res.push(arr[len-1].val) 45 | for(let i=0;i=m),从`m`到`n`的过程中,这个位置进位了,一旦发生进位,前面的每一位都要经过一次`0`,因此前面全部为`0`。 45 | 46 | 最后将结果解析为数字。 47 | 48 | ``` 49 | /** 50 | * @param {number} m 51 | * @param {number} n 52 | * @return {number} 53 | */ 54 | var rangeBitwiseAnd = function(m, n) { 55 | let k=Math.pow(2,30) 56 | let str='' 57 | for(let i=0;i<31;i++){ 58 | let c1=(m<2->6->3->4->5->6, **val** = 6 17 | 输出: 1->2->3->4->5 18 | ``` 19 | 20 | 21 | 22 | ----- 23 | 24 | 思路: 25 | 26 | 只需要时刻跟踪当前`node`和当前`node`的上一个节点`lastNode`。 27 | 28 | 遇到`node.val===val`,那么就改变`lastNode.next`为`node.next`。 29 | 30 | ``` 31 | /** 32 | * Definition for singly-linked list. 33 | * function ListNode(val) { 34 | * this.val = val; 35 | * this.next = null; 36 | * } 37 | */ 38 | /** 39 | * @param {ListNode} head 40 | * @param {number} val 41 | * @return {ListNode} 42 | */ 43 | var removeElements = function(head, val) { 44 | let root=new ListNode(null) 45 | root.next=head 46 | let lastNode=root,node=head 47 | while(lastNode){ 48 | if(node && node.val===val){ 49 | let nxt=node.next 50 | lastNode.next=nxt 51 | node=nxt 52 | }else{ 53 | if(node)node=node.next 54 | lastNode=lastNode.next 55 | } 56 | } 57 | return root.next 58 | }; 59 | ``` 60 | 61 | -------------------------------------------------------------------------------- /201-300/204.md: -------------------------------------------------------------------------------- 1 | ### 204. 计数质数 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`哈希表`、`数学` 6 | 7 | 统计所有小于非负整数*n* 的质数的数量。 8 | 9 | 10 | 11 | **示例:** 12 | 13 | 14 | 15 | ``` 16 | 输入: 10 17 | 输出: 4 18 | 解释: 小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。 19 | ``` 20 | 21 | 22 | 23 | ----- 24 | 25 | 思路: 26 | 27 | 厄拉多塞筛法,比`Math.sqrt`+`for in primes`加起来还快。 28 | 29 | 它是定义一个数组`notPrime`,表示非质数的数,`0`和`1`不是质数。 30 | 31 | 接着`2`是第一个质数,然后把范围内所有2的倍数在`notPrime[2的倍数]=true`, 32 | 33 | 接着`3`不在`notPrime`范围内,因此是下一个质数,然后把3所有的倍数设置为`true` 34 | 35 | 以此类推... 36 | 37 | ``` 38 | /** 39 | * @param {number} n 40 | * @return {number} 41 | */ 42 | var countPrimes = function(n) { 43 | let notPrime = new Array(n); 44 | let count = 0; 45 | notPrime[0] = true; 46 | notPrime[1] = true; 47 | for (let i = 1; i < n; i=i+2){ 48 | if (!notPrime[i]){ 49 | count++; 50 | // 对当前质数的所有倍数都定义为非质数,这里从 i*i开始,因为之前的已经计算过了 51 | for (let j = i*i; j < n; j += i){ 52 | notPrime[j] = true; 53 | } 54 | } 55 | } 56 | return n>2?count+1:count; 57 | }; 58 | ``` 59 | 60 | -------------------------------------------------------------------------------- /201-300/206.md: -------------------------------------------------------------------------------- 1 | ### 206. 反转链表 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`链表` 6 | 7 | 反转一个单链表。 8 | 9 | 10 | 11 | **示例:** 12 | 13 | 14 | 15 | ``` 16 | 输入: 1->2->3->4->5->NULL 17 | 输出: 5->4->3->2->1->NULL 18 | ``` 19 | 20 | 21 | **进阶:** 22 | 你可以迭代或递归地反转链表。你能否用两种方法解决这道题? 23 | 24 | 25 | ``` 26 | /** 27 | * Definition for singly-linked list. 28 | * function ListNode(val) { 29 | * this.val = val; 30 | * this.next = null; 31 | * } 32 | */ 33 | /** 34 | * @param {ListNode} head 35 | * @return {ListNode} 36 | */ 37 | var reverseList = function(head) { 38 | function iteratively (node){ 39 | let prev=null 40 | while(node){ 41 | let next=node.next 42 | node.next=prev 43 | prev=node 44 | node=next 45 | } 46 | return prev 47 | } 48 | 49 | 50 | function recursively (node){ 51 | if(!node || !node.next)return node 52 | let r=recursively(node.next) 53 | node.next.next=node 54 | node.next=null 55 | return r 56 | } 57 | 58 | return recursively(head) 59 | }; 60 | ``` 61 | 62 | -------------------------------------------------------------------------------- /201-300/216.md: -------------------------------------------------------------------------------- 1 | ### 216. 组合总和 III 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`数组`、`回溯算法` 6 | 7 | 找出所有相加之和为***n*** 的***k*** 个数的组合***。*** 组合中只允许含有 1 -9 的正整数,并且每种组合中不存在重复的数字。 8 | 9 | 10 | 11 | **说明:** 12 | 13 | 14 | 15 | 16 | * 所有数字都是正整数。 17 | 18 | * 解集不能包含重复的组合。 19 | 20 | 21 | 22 | 23 | 24 | **示例 1:** 25 | 26 | 27 | 28 | ``` 29 | 输入: **k** = 3, **n** = 7 30 | 输出: [[1,2,4]] 31 | ``` 32 | 33 | 34 | **示例 2:** 35 | 36 | 37 | 38 | ``` 39 | 输入: **k** = 3, **n** = 9 40 | 输出: [[1,2,6], [1,3,5], [2,3,4]] 41 | ``` 42 | 43 | ``` 44 | /** 45 | * @param {number} k 46 | * @param {number} n 47 | * @return {number[][]} 48 | */ 49 | var combinationSum3 = function(k, n) { 50 | let validNum=[] 51 | let res=[] 52 | let cache={} 53 | function getSumComb(sum,validNum,times,start){ 54 | if(times===0){ 55 | if(sum===0)res.push(validNum.slice()) 56 | return 57 | } 58 | for(let i=start;i<=9;i++){ 59 | validNum.push(i) 60 | getSumComb(sum-i,validNum,times-1,i+1) 61 | validNum.pop() 62 | } 63 | } 64 | getSumComb(n,validNum,k,1) 65 | return res 66 | }; 67 | ``` 68 | 69 | -------------------------------------------------------------------------------- /201-300/217.md: -------------------------------------------------------------------------------- 1 | ### 217. 存在重复元素 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`数组`、`哈希表` 6 | 7 | 给定一个整数数组,判断是否存在重复元素。 8 | 9 | 10 | 11 | 如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。 12 | 13 | 14 | 15 | **示例 1:** 16 | 17 | 18 | 19 | ``` 20 | 输入: [1,2,3,1] 21 | 输出: true 22 | ``` 23 | 24 | 25 | **示例 2:** 26 | 27 | 28 | 29 | ``` 30 | 输入:[1,2,3,4] 31 | 输出: false 32 | ``` 33 | 34 | 35 | **示例3:** 36 | 37 | 38 | 39 | ``` 40 | 输入:[1,1,1,3,3,4,3,2,4,2] 41 | 输出: true 42 | ``` 43 | 44 | ``` 45 | /** 46 | * @param {number[]} nums 47 | * @return {boolean} 48 | */ 49 | var containsDuplicate = function(nums) { 50 | let res=[] 51 | for(let i=0;i0 && j>0)lt=dp[i-1][j-1] 42 | if(i>0)t=dp[i-1][j] 43 | if(j>0)l=dp[i][j-1] 44 | dp[i][j]=Math.min(lt,l,t)+1 45 | max=Math.max(max,dp[i][j]) 46 | } 47 | } 48 | } 49 | return max*max 50 | }; 51 | ``` 52 | 53 | -------------------------------------------------------------------------------- /201-300/222.md: -------------------------------------------------------------------------------- 1 | ### 222. 完全二叉树的节点个数 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`树`、`二分查找` 6 | 7 | 给出一个**完全二叉树** ,求出该树的节点个数。 8 | 9 | 10 | 11 | **说明:** 12 | 13 | 14 | 15 | [完全二叉树](https://baike.baidu.com/item/%E5%AE%8C%E5%85%A8%E4%BA%8C%E5%8F%89%E6%A0%91/7773232?fr=aladdin) 16 | 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~2h个节点。 17 | 18 | 19 | 20 | **示例:** 21 | 22 | 23 | 24 | ``` 25 | 输入: 26 | 1 27 | / \ 28 | 2 3 29 | / \ / 30 | 4 5 6 31 | 32 | 输出: 6 33 | ``` 34 | 35 | ``` 36 | /** 37 | * Definition for a binary tree node. 38 | * function TreeNode(val) { 39 | * this.val = val; 40 | * this.left = this.right = null; 41 | * } 42 | */ 43 | /** 44 | * @param {TreeNode} root 45 | * @return {number} 46 | */ 47 | var countNodes = function(root) { 48 | if(!root)return 0 49 | let count=1 50 | count+=countNodes(root.left) 51 | count+=countNodes(root.right) 52 | return count 53 | 54 | }; 55 | ``` 56 | 57 | -------------------------------------------------------------------------------- /201-300/223.md: -------------------------------------------------------------------------------- 1 | ### 223. 矩形面积 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`数学` 6 | 7 | 在**二维** 平面上计算出两个**由直线构成的** 矩形重叠后形成的总面积。 8 | 9 | 10 | 11 | 每个矩形由其左下顶点和右上顶点坐标表示,如图所示。 12 | 13 | 14 | 15 | ![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2018/10/22/rectangle_area.png) 16 | 17 | 18 | 19 | 20 | **示例:** 21 | 22 | 23 | 24 | ``` 25 | 输入: -3, 0, 3, 4, 0, -1, 9, 2 26 | 输出: 45 27 | ``` 28 | 29 | 30 | **说明:** 假设矩形面积不会超出**int** 的范围。 31 | 32 | 33 | ``` 34 | /** 35 | * @param {number} A 36 | * @param {number} B 37 | * @param {number} C 38 | * @param {number} D 39 | * @param {number} E 40 | * @param {number} F 41 | * @param {number} G 42 | * @param {number} H 43 | * @return {number} 44 | */ 45 | var computeArea = function(A, B, C, D, E, F, G, H) { 46 | let gapX1=[A,C],gapX2=[E,G], 47 | gapY1=[B,D],gapY2=[F,H] 48 | let ox1=Math.max(A,E),ox2=Math.min(C,G) 49 | let oy1=Math.max(B,F),oy2=Math.min(D,H) 50 | let gap_x=0,gap_y=0 51 | if(ox2>ox1)gap_x=ox2-ox1 52 | if(oy2>oy1)gap_y=oy2-oy1 53 | let allArea=(C-A)*(D-B)+(G-E)*(H-F) 54 | return allArea-gap_x*gap_y 55 | }; 56 | ``` 57 | 58 | -------------------------------------------------------------------------------- /201-300/228.md: -------------------------------------------------------------------------------- 1 | ### 228. 汇总区间 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`数组` 6 | 7 | 给定一个无重复元素的有序整数数组,返回数组区间范围的汇总。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | 14 | 15 | ``` 16 | 输入: [0,1,2,4,5,7] 17 | 输出: ["0->2","4->5","7"] 18 | 解释:0,1,2 可组成一个连续的区间;4,5 可组成一个连续的区间。 19 | ``` 20 | 21 | 22 | **示例 2:** 23 | 24 | 25 | 26 | ``` 27 | 输入: [0,2,3,4,6,8,9] 28 | 输出: ["0","2->4","6","8->9"] 29 | 解释:2,3,4 可组成一个连续的区间;8,9 可组成一个连续的区间。 30 | ``` 31 | 32 | ``` 33 | /** 34 | * @param {number[]} nums 35 | * @return {string[]} 36 | */ 37 | var summaryRanges = function(nums) { 38 | let result=[] 39 | if(nums.length===0)return result 40 | let head=nums[0], 41 | tail=null 42 | for(let i=1;i'+tail) 47 | tail=null 48 | }else{ 49 | result.push(''+head) 50 | } 51 | head=nums[i] 52 | } 53 | } 54 | if(tail)result.push(head+'->'+tail) 55 | else result.push(''+head) 56 | return result 57 | }; 58 | ``` 59 | 60 | -------------------------------------------------------------------------------- /201-300/231.md: -------------------------------------------------------------------------------- 1 | ### 231. 2的幂 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`位运算`、`数学` 6 | 7 | 给定一个整数,编写一个函数来判断它是否是 2 的幂次方。 8 | 9 | 10 | 11 | **示例1:** 12 | 13 | 14 | 15 | ``` 16 | 输入: 1 17 | 输出: true 18 | 解释:20= 1 19 | ``` 20 | 21 | 22 | **示例 2:** 23 | 24 | 25 | 26 | ``` 27 | 输入: 16 28 | 输出: true 29 | 解释:24= 16 30 | ``` 31 | 32 | 33 | **示例 3:** 34 | 35 | 36 | 37 | ``` 38 | 输入: 218 39 | 输出: false 40 | ``` 41 | 42 | ``` 43 | /** 44 | * @param {number} n 45 | * @return {boolean} 46 | */ 47 | var isPowerOfTwo = function(n) { 48 | if(n<=0) return false; 49 | return !(n&(n-1)); 50 | }; 51 | ``` 52 | 53 | -------------------------------------------------------------------------------- /201-300/233.md: -------------------------------------------------------------------------------- 1 | ### 233. 数字 1 的个数 2 | 3 | 难度:Hard 4 | 5 | 相关话题:`数学` 6 | 7 | 给定一个整数 n,计算所有小于等于 n 的非负整数中数字 1 出现的个数。 8 | 9 | 10 | 11 | **示例:** 12 | 13 | 14 | 15 | ``` 16 | 输入: 13 17 | 输出: 6 18 | 解释:数字 1 出现在以下数字中: 1, 10, 11, 12, 13 。 19 | ``` 20 | 21 | ``` 22 | /** 23 | * @param {number} n 24 | * @return {number} 25 | */ 26 | var countDigitOne = function(n) { 27 | if(n<0)return 0 28 | let s=n+'' 29 | function count(s){ 30 | if(s==='' || +s===0)return 0 31 | let head=+s[0] 32 | // 例如782,rest为count('99') 33 | // 因为对语0XX~6XX,每一个都存在 99 个尾巴 34 | let rest=count('9'.repeat(s.length-1)) 35 | let res=0 36 | for(let i=0;i=0 && curCtarget)curR-- 62 | else return true 63 | } 64 | return false 65 | }; 66 | ``` 67 | 68 | -------------------------------------------------------------------------------- /201-300/242.md: -------------------------------------------------------------------------------- 1 | ### 242. 有效的字母异位词 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`排序`、`哈希表` 6 | 7 | 给定两个字符串 *s* 和 *t* ,编写一个函数来判断 *t* 是否是 *s* 的一个字母异位词。 8 | 9 | 10 | 11 | **示例1:** 12 | 13 | 14 | 15 | ``` 16 | 输入: s = "anagram", t = "nagaram" 17 | 输出: true 18 | ``` 19 | 20 | 21 | **示例 2:** 22 | 23 | 24 | 25 | ``` 26 | 输入: s = "rat", t = "car" 27 | 输出:false 28 | ``` 29 | 30 | 31 | **说明:** 32 | 你可以假设字符串只包含小写字母。 33 | 34 | 35 | 36 | **进阶:** 37 | 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况? 38 | 39 | 40 | 41 | 42 | ----- 43 | 44 | 思路: 45 | 46 | 对`s`每一个字母对应的索引`+1`,对`t`每一个字母对应的索引`-1`,如果存在负值,返回`false`。 47 | 48 | ``` 49 | /** 50 | * @param {string} s 51 | * @param {string} t 52 | * @return {boolean} 53 | */ 54 | var isAnagram = function(s, t) { 55 | if(s.length!==t.length)return false 56 | let codes=Array(26).fill(0) 57 | for(let i=0;i2->5", "1->3"] 29 | 30 | 解释: 所有根节点到叶子节点的路径为: 1->2->5, 1->3 31 | ``` 32 | 33 | ``` 34 | /** 35 | * Definition for a binary tree node. 36 | * function TreeNode(val) { 37 | * this.val = val; 38 | * this.left = this.right = null; 39 | * } 40 | */ 41 | /** 42 | * @param {TreeNode} root 43 | * @return {string[]} 44 | */ 45 | var binaryTreePaths = function(root) { 46 | if(!root)return [] 47 | let str=root.val+'' 48 | let result=[] 49 | pre(str,root) 50 | function pre(str,node){ 51 | if(node.left)pre(str+'->'+node.left.val,node.left) 52 | if(node.right)pre(str+'->'+node.right.val,node.right) 53 | if(!node.left && !node.right)result.push(str) 54 | } 55 | return result 56 | }; 57 | ``` 58 | 59 | -------------------------------------------------------------------------------- /201-300/258.md: -------------------------------------------------------------------------------- 1 | ### 258. 各位相加 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`数学` 6 | 7 | 给定一个非负整数 `num` ,反复将各个位上的数字相加,直到结果为一位数。 8 | 9 | 10 | 11 | **示例:** 12 | 13 | 14 | 15 | ``` 16 | 输入: 38 17 | 输出: 2 18 | 解释:各位相加的过程为:3 + 8 = 11, 1 + 1 = 2。 由于2 是一位数,所以返回 2。 19 | ``` 20 | 21 | 22 | **进阶:** 23 | 你可以不使用循环或者递归,且在 O(1) 时间复杂度内解决这个问题吗? 24 | 25 | 26 | ``` 27 | /** 28 | * @param {number} num 29 | * @return {number} 30 | */ 31 | var addDigits = function(num) { 32 | while(num>=10){ 33 | let x=parseInt(num/10,10)+num%10 34 | num=x 35 | } 36 | return num 37 | 38 | // O(1) 39 | // return (num % 9 === 0) ? (num === 0 ? 0 : 9) : num % 9 40 | }; 41 | ``` 42 | 43 | -------------------------------------------------------------------------------- /201-300/260.md: -------------------------------------------------------------------------------- 1 | ### 260. 只出现一次的数字 III 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`位运算` 6 | 7 | 给定一个整数数组 `nums` ,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。 8 | 9 | 10 | 11 | **示例 :** 12 | 13 | 14 | 15 | ``` 16 | 输入: [1,2,1,3,2,5] 17 | 输出: [3,5] 18 | ``` 19 | 20 | 21 | **注意:** 22 | 23 | 24 | 25 | 26 | 1. 结果输出的顺序并不重要,对于上面的例子, `[5, 3]` 也是正确答案。 27 | 28 | 2. 你的算法应该具有线性时间复杂度。你能否仅使用常数空间复杂度来实现? 29 | 30 | 31 | 32 | 33 | 34 | 35 | ----- 36 | 37 | 思路: 38 | 39 | 2次遍历,第一次遍历计算所有数的`xor`,计算`xor`的原因是因为只要找到`xor`二进制中最后一位`1`的位置, 40 | 那么说明那`2`个独立的数这个位置上的数字是不同的(这样它们才有可能异或`1`)。 41 | 42 | 第二次遍历,如果当前数的那个位置是`1`,单独计算异或值;如果是`0`,也单独计算异或值,最终得到2个不同的独立值。 43 | 44 | ``` 45 | /** 46 | * @param {number[]} nums 47 | * @return {number[]} 48 | */ 49 | var singleNumber = function(nums) { 50 | let xor=0 51 | for(let num of nums)xor ^= num 52 | // 找出xor的二进制中最后一个1及后面的0代表的数字 53 | // 这个最后一个1的位置 说明这两个出现1次的数在这个位置的数是1和0 54 | let lastOneBit=1 55 | while(xor % 2===0){ 56 | xor /= 2 57 | lastOneBit*=2 58 | } 59 | let res=[0,0] 60 | for(let num of nums){ 61 | // 这个位置是0的所有数 62 | if((lastOneBit & num)===0){ 63 | res[0] ^= num 64 | }else{ 65 | // 这个位置是1的所有数 66 | res[1] ^= num 67 | } 68 | } 69 | return res 70 | }; 71 | ``` 72 | 73 | -------------------------------------------------------------------------------- /201-300/263.md: -------------------------------------------------------------------------------- 1 | ### 263. 丑数 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`数学` 6 | 7 | 编写一个程序判断给定的数是否为丑数。 8 | 9 | 10 | 11 | 丑数就是只包含质因数 `2, 3, 5` 的**正整数** 。 12 | 13 | 14 | 15 | **示例 1:** 16 | 17 | 18 | 19 | ``` 20 | 输入: 6 21 | 输出: true 22 | 解释:6 = 2 ×3 23 | ``` 24 | 25 | 26 | **示例 2:** 27 | 28 | 29 | 30 | ``` 31 | 输入: 8 32 | 输出: true 33 | 解释:8 = 2 × 2 ×2 34 | ``` 35 | 36 | 37 | **示例3:** 38 | 39 | 40 | 41 | ``` 42 | 输入: 14 43 | 输出: false 44 | 解释:14 不是丑数,因为它包含了另外一个质因数7。 45 | ``` 46 | 47 | 48 | **说明:** 49 | 50 | 51 | 52 | 53 | 1. `1` 是丑数。 54 | 55 | 2. 输入不会超过 32 位有符号整数的范围:[−231, 231− 1]。 56 | 57 | 58 | 59 | 60 | ``` 61 | /** 62 | * @param {number} num 63 | * @return {boolean} 64 | */ 65 | var isUgly = function(num) { 66 | if(num===0)return false 67 | while(num%2===0){ 68 | num=num/2 69 | } 70 | while(num%3===0){ 71 | num=num/3 72 | } 73 | while(num%5===0){ 74 | num=num/5 75 | } 76 | return num===1?true:false 77 | }; 78 | ``` 79 | 80 | -------------------------------------------------------------------------------- /201-300/268.md: -------------------------------------------------------------------------------- 1 | ### 268. 缺失数字 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`位运算`、`数组`、`数学` 6 | 7 | 给定一个包含 `0, 1, 2, ..., n` 中*n* 个数的序列,找出 0 .. *n* 中没有出现在序列中的那个数。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | 14 | 15 | ``` 16 | 输入: [3,0,1] 17 | 输出: 2 18 | ``` 19 | 20 | 21 | **示例2:** 22 | 23 | 24 | 25 | ``` 26 | 输入: [9,6,4,2,3,5,7,0,1] 27 | 输出: 8 28 | ``` 29 | 30 | 31 | **说明:** 32 | 你的算法应具有线性时间复杂度。你能否仅使用额外常数空间来实现? 33 | 34 | 35 | ``` 36 | /** 37 | * @param {number[]} nums 38 | * @return {number} 39 | */ 40 | var missingNumber = function(nums) { 41 | let sum=0,len=nums.length 42 | for(let i=0;ifalse 50 | if(n===0)return false 51 | return !!(n%4) 52 | }; 53 | ``` 54 | 55 | -------------------------------------------------------------------------------- /301-400/303.md: -------------------------------------------------------------------------------- 1 | ### 303. 区域和检索 - 数组不可变 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`动态规划` 6 | 7 | 给定一个整数数组 *nums* ,求出数组从索引*i* 到*j* (*i* ≤*j* ) 范围内元素的总和,包含*i, j* 两点。 8 | 9 | 10 | 11 | **示例:** 12 | 13 | 14 | 15 | ``` 16 | 给定 nums = [-2, 0, 3, -5, 2, -1],求和函数为 sumRange() 17 | 18 | sumRange(0, 2) -> 1 19 | sumRange(2, 5) -> -1 20 | sumRange(0, 5) -> -3 21 | ``` 22 | 23 | 24 | **说明:** 25 | 26 | 27 | 28 | 29 | 1. 你可以假设数组不可变。 30 | 31 | 2. 会多次调用*sumRange* 方法。 32 | 33 | 34 | 35 | 36 | ``` 37 | /** 38 | * @param {number[]} nums 39 | */ 40 | var NumArray = function(nums) { 41 | this.sums = []; 42 | let sum = 0; 43 | for(let i=0; i nums[2] < nums[3]...` 的顺序。 8 | 9 | 10 | 11 | **示例1:** 12 | 13 | 14 | 15 | ``` 16 | 输入:nums = [1, 5, 1, 1, 6, 4] 17 | 输出:一个可能的答案是 [1, 4, 1, 5, 1, 6] 18 | ``` 19 | 20 | 21 | **示例 2:** 22 | 23 | 24 | 25 | ``` 26 | 输入:nums = [1, 3, 2, 2, 3, 1] 27 | 输出: 一个可能的答案是 [2, 3, 1, 3, 1, 2] 28 | ``` 29 | 30 | 31 | **说明:** 32 | 你可以假设所有输入都会得到有效的结果。 33 | 34 | 35 | 36 | **进阶:** 37 | 你能用O(n) 时间复杂度和 / 或原地 O(1) 额外空间来实现吗? 38 | 39 | 40 | 41 | 42 | ----- 43 | 44 | 思路: 45 | 46 | 对`nums`从小到大排序,之后2个指针,指针1`left`初始在中间,指针2`right`初始在末尾,向左移动并且逐个配对。 47 | 48 | ``` 49 | /** 50 | * @param {number[]} nums 51 | * @return {void} Do not return anything, modify nums in-place instead. 52 | */ 53 | var wiggleSort = function(nums) { 54 | let arr=nums.slice() 55 | arr.sort((a,b)=>a-b) 56 | var len = nums.length 57 | var left = Math.ceil(len/2)-1 58 | var right = len-1 59 | for(var i = 0; i0 && Math.pow(3,19) % n===0) 68 | }; 69 | ``` 70 | 71 | -------------------------------------------------------------------------------- /301-400/338.md: -------------------------------------------------------------------------------- 1 | ### 338. 比特位计数 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`位运算`、`动态规划` 6 | 7 | 给定一个非负整数**num** 。对于**0 ≤ i ≤ num** 范围中的每个数字**i** ,计算其二进制数中的 1 的数目并将它们作为数组返回。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | 14 | 15 | ``` 16 | 输入:2 17 | 输出:[0,1,1] 18 | ``` 19 | 20 | 21 | **示例2:** 22 | 23 | 24 | 25 | ``` 26 | 输入:5 27 | 输出:[0,1,1,2,1,2] 28 | ``` 29 | 30 | 31 | **进阶:** 32 | 33 | 34 | 35 | 36 | * 给出时间复杂度为**O(n*sizeof(integer))** 的解答非常容易。但你可以在线性时间**O(n)** 内用一趟扫描做到吗? 37 | 38 | * 要求算法的空间复杂度为**O(n)** 。 39 | 40 | * 你能进一步完善解法吗?要求在C++或任何其他语言中不使用任何内置函数(如 C++ 中的**__builtin_popcount** )来执行此操作。 41 | 42 | 43 | 44 | 45 | ``` 46 | /** 47 | * @param {number} num 48 | * @return {number[]} 49 | */ 50 | var countBits = function(num) { 51 | let dp=[0,1] 52 | let p=Math.floor(Math.log2(num)) 53 | for(let i=1;i<=p;i++){ 54 | fillpow(i) 55 | } 56 | function fillpow(p){ 57 | let prev=Math.pow(2,p-1) 58 | let cur=Math.pow(2,p) 59 | let next=Math.pow(2,p+1) 60 | for(let i=prev;i 0 && (num & (num - 1)) == 0 && (num - 1) % 3 == 0; 42 | }; 43 | ``` 44 | 45 | -------------------------------------------------------------------------------- /301-400/343.md: -------------------------------------------------------------------------------- 1 | ### 343. 整数拆分 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`数学`、`动态规划` 6 | 7 | 给定一个正整数*n* ,将其拆分为**至少** 两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | 14 | 15 | ``` 16 | 输入:2 17 | 输出:1 18 | 解释:2 = 1 + 1, 1 × 1 = 1。 19 | ``` 20 | 21 | 22 | **示例2:** 23 | 24 | 25 | 26 | ``` 27 | 输入:10 28 | 输出:36 29 | 解释:10 = 3 + 3 + 4, 3 ×3 ×4 = 36。 30 | ``` 31 | 32 | 33 | **说明:** 你可以假设*n* 不小于 2 且不大于 58。 34 | 35 | 36 | ``` 37 | /** 38 | * @param {number} n 39 | * @return {number} 40 | */ 41 | var integerBreak = function(n) { 42 | if(n===2)return 1 43 | if(n===3)return 2 44 | if(n===4)return 4 45 | let res=1 46 | while(n>4){ 47 | res*=3 48 | n=n-3 49 | } 50 | return res*n 51 | // let c={ 52 | // 2:1, 53 | // 3:2, 54 | // 4:4, 55 | // 5:6, 56 | // 6:9, 57 | // } 58 | // if(n<7) return c[n] 59 | 60 | // function getMax(n){ 61 | // if(n<=4)return n 62 | // return getMax(n-3)*3 63 | // } 64 | // return getMax(n) 65 | }; 66 | ``` 67 | 68 | -------------------------------------------------------------------------------- /301-400/344.md: -------------------------------------------------------------------------------- 1 | ### 344. 反转字符串 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`双指针`、`字符串` 6 | 7 | 编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 `char[]` 的形式给出。 8 | 9 | 10 | 11 | 不要给另外的数组分配额外的空间,你必须**[原地](https://baike.baidu.com/item/原地算法) 12 | 修改输入数组** 、使用 O(1) 的额外空间解决这一问题。 13 | 14 | 15 | 16 | 你可以假设数组中的所有字符都是 [ASCII](https://baike.baidu.com/item/ASCII) 17 | 码表中的可打印字符。 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | **示例 1:** 26 | 27 | 28 | 29 | ``` 30 | 输入:["h","e","l","l","o"] 31 | 输出:["o","l","l","e","h"] 32 | ``` 33 | 34 | 35 | **示例 2:** 36 | 37 | 38 | 39 | ``` 40 | 输入:["H","a","n","n","a","h"] 41 | 输出:["h","a","n","n","a","H"] 42 | ``` 43 | 44 | ``` 45 | /** 46 | * @param {character[]} s 47 | * @return {void} Do not return anything, modify s in-place instead. 48 | */ 49 | var reverseString = function(s) { 50 | for(let i=0;i 1 && availableNumber > 0) { 33 | uniqueDigits = uniqueDigits * availableNumber; 34 | res += uniqueDigits; 35 | availableNumber--; 36 | } 37 | return res; 38 | }; 39 | ``` 40 | 41 | -------------------------------------------------------------------------------- /301-400/367.md: -------------------------------------------------------------------------------- 1 | ### 367. 有效的完全平方数 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`数学`、`二分查找` 6 | 7 | 给定一个正整数 *num* ,编写一个函数,如果 *num* 是一个完全平方数,则返回 True,否则返回 False。 8 | 9 | 10 | 11 | **说明:** 不要使用任何内置的库函数,如 `sqrt` 。 12 | 13 | 14 | 15 | **示例 1:** 16 | 17 | 18 | 19 | ``` 20 | 输入:16 21 | 输出:True 22 | ``` 23 | 24 | 25 | **示例 2:** 26 | 27 | 28 | 29 | ``` 30 | 输入:14 31 | 输出:False 32 | ``` 33 | 34 | ``` 35 | /** 36 | * @param {number} num 37 | * @return {boolean} 38 | */ 39 | var isPerfectSquare = function(num) { 40 | let lo=1, 41 | hi=Number.MAX_SAFE_INTEGER 42 | while(lonum)hi=mid 47 | else return true 48 | } 49 | return false 50 | }; 51 | ``` 52 | 53 | -------------------------------------------------------------------------------- /301-400/371.md: -------------------------------------------------------------------------------- 1 | ### 371. 两整数之和 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`位运算` 6 | 7 | **不使用** 运算符 `+` 和 `-` ​​​​​​​,计算两整数​​​​​​​ `a` 、 `b` ​​​​​​​之和。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | 14 | 15 | ``` 16 | 输入:a = 1, b = 2 17 | 输出:3 18 | ``` 19 | 20 | 21 | **示例 2:** 22 | 23 | 24 | 25 | ``` 26 | 输入:a = -2, b = 3 27 | 输出:1 28 | ``` 29 | 30 | ``` 31 | /** 32 | * @param {number} a 33 | * @param {number} b 34 | * @return {number} 35 | */ 36 | var getSum = function(a, b) { 37 | let aS=Math.abs(a),bS=Math.abs(b) 38 | let i=Math.min(aS,bS), 39 | j=Math.max(aS,bS); 40 | let sum 41 | if(a*b>0){ 42 | let t=i/j 43 | let s=String(t) 44 | s='1'.concat(s.substr(1)) 45 | sum=parseFloat(s)*j*((a<0 && b<0)?-1:1) 46 | }else if(a*b<0){ 47 | let t=j/i 48 | let s=String(t) 49 | s='0'.concat(s.substr(1)) 50 | sum=parseFloat(s)*i*(j*-1===a||j*-1===b?-1:1) 51 | }else if(a===0)return b 52 | else return a 53 | return sum 54 | }; 55 | ``` 56 | 57 | -------------------------------------------------------------------------------- /301-400/372.md: -------------------------------------------------------------------------------- 1 | ### 372. 超级次方 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`数学` 6 | 7 | 你的任务是计算*a* *b* 对1337 取模,*a* 是一个正整数,*b* 是一个非常大的正整数且会以数组形式给出。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | 14 | 15 | ``` 16 | 输入:a = 2, b = [3] 17 | 输出:8 18 | ``` 19 | 20 | 21 | **示例2:** 22 | 23 | 24 | 25 | ``` 26 | 输入:a = 2, b = [1,0] 27 | 输出:1024 28 | ``` 29 | 30 | 31 | 32 | ----- 33 | 34 | 思路: 35 | 36 | 一个次方的转换`a^12345 === a^5 * a^10^4 * a^100^3 * a^1000^2 * a^10000^1` 37 | 38 | 反向遍历`b`,每次遍历`a=pow(a,10)`,然后再求`pow(a,b[i])` 39 | 40 | 这里`pow`函数很好写,就是普通的次方再`%MOD` 41 | 42 | ``` 43 | /** 44 | * @param {number} a 45 | * @param {number[]} b 46 | * @return {number} 47 | */ 48 | var superPow = function(a, b) { 49 | let MOD=1337 50 | let sum=1 51 | for(let i=b.length-1;i>=0;i--){ 52 | sum = sum * getPow(a % MOD, b[i]) % MOD 53 | a = getPow(a,10) 54 | } 55 | return sum 56 | function getPow(n,p){ 57 | let sum=1 58 | for(let i=0;i false 26 | canConstruct("aa", "ab") -> false 27 | canConstruct("aa", "aab") -> true 28 | ``` 29 | 30 | ``` 31 | /** 32 | * @param {string} ransomNote 33 | * @param {string} magazine 34 | * @return {boolean} 35 | */ 36 | var canConstruct = function(ransomNote, magazine) { 37 | let map={},ran=ransomNote,mag=magazine 38 | for(let i=0;i0)return false 48 | } 49 | return true 50 | }; 51 | ``` 52 | 53 | -------------------------------------------------------------------------------- /301-400/386.md: -------------------------------------------------------------------------------- 1 | ### 386. 字典序排数 2 | 3 | 难度:Middle 4 | 5 | 相关话题: 6 | 7 | 给定一个整数*n* , 返回从*1* 到*n* 的字典顺序。 8 | 9 | 10 | 11 | 例如, 12 | 13 | 14 | 15 | 给定 *n* =1 3,返回 [1,10,11,12,13,2,3,4,5,6,7,8,9] 。 16 | 17 | 18 | 19 | 请尽可能的优化算法的时间复杂度和空间复杂度。 输入的数据*n* 小于等于5,000,000。 20 | 21 | 22 | 23 | 24 | ----- 25 | 26 | 思路: 27 | 28 | 最直观就是排序。 29 | 30 | 时间复杂度`O(N)`的解决方案,对于以`1`开头的,存在`10,11,12...19`,对于`10`开头的,存在`100,101,102...109`; 31 | 32 | 因此对于从`1`到`9`每一个数,递归以它们开头的每一个数字,添加到结果。 33 | 34 | ``` 35 | /** 36 | * @param {number} n 37 | * @return {number[]} 38 | */ 39 | var lexicalOrder = function(n) { 40 | let result=[] 41 | for(let i=1;i<10;i++){ 42 | dfs(result,i) 43 | } 44 | function dfs(result,cur){ 45 | if(cur>n)return 46 | result.push(cur) 47 | for(let i=0;i<10;i++){ 48 | if((10*cur+i)>n)return 49 | dfs(result,10*cur+i) 50 | } 51 | } 52 | return result 53 | }; 54 | ``` 55 | 56 | -------------------------------------------------------------------------------- /301-400/387.md: -------------------------------------------------------------------------------- 1 | ### 387. 字符串中的第一个唯一字符 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`哈希表`、`字符串` 6 | 7 | 给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。 8 | 9 | 10 | 11 | **案例:** 12 | 13 | 14 | 15 | ``` 16 | 17 | s = "leetcode" 18 | 返回 0. 19 | 20 | s = "loveleetcode", 21 | 返回 2. 22 | ``` 23 | 24 | 25 | 26 | 27 | 28 | 29 | **注意事项:** 您可以假定该字符串只包含小写字母。 30 | 31 | 32 | ``` 33 | /** 34 | * @param {string} s 35 | * @return {number} 36 | */ 37 | var firstUniqChar = function(s) { 38 | let mem=Array(26).fill(0) 39 | for(let i=0;i= 0 || j >= 0 || carry === 1) { 36 | let n1 = i >= 0 ? num1[i--] : 0; 37 | let n2 = j >= 0 ? num2[j--] : 0; 38 | let sum = carry + n1 % 10 + n2 % 10; 39 | carry = Math.trunc(sum / 10); 40 | ret = (sum % 10) + ret; 41 | } 42 | return ret; 43 | 44 | }; 45 | ``` 46 | 47 | -------------------------------------------------------------------------------- /401-500/416.md: -------------------------------------------------------------------------------- 1 | ### 416. 分割等和子集 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`动态规划` 6 | 7 | 给定一个**只包含正整数** 的**非空** 数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。 8 | 9 | 10 | 11 | **注意:** 12 | 13 | 14 | 15 | 16 | 1. 每个数组中的元素不会超过 100 17 | 18 | 2. 数组的大小不会超过 200 19 | 20 | 21 | 22 | 23 | 24 | **示例 1:** 25 | 26 | 27 | 28 | ``` 29 | 输入: [1, 5, 11, 5] 30 | 31 | 输出: true 32 | 33 | 解释: 数组可以分割成 [1, 5, 5] 和 [11]. 34 | ``` 35 | 36 | 37 | 38 | 39 | 40 | 41 | **示例2:** 42 | 43 | 44 | 45 | ``` 46 | 输入: [1, 2, 3, 5] 47 | 48 | 输出: false 49 | 50 | 解释: 数组不能分割成两个元素和相等的子集. 51 | ``` 52 | 53 | 54 | 55 | 56 | 57 | ``` 58 | /** 59 | * @param {number[]} nums 60 | * @return {boolean} 61 | */ 62 | var canPartition = function(nums) { 63 | let allSum=nums.reduce((sum,cur)=>sum+cur,0) 64 | if(allSum % 2!==0)return false 65 | let sum=allSum/2 66 | let aux=Array(sum+1).fill(0) 67 | aux[0]=1 68 | for(let n of nums){ 69 | for(let i=sum;i>=n;i--){ 70 | aux[i]+=aux[i-n] 71 | } 72 | if(aux[sum]>0)return true 73 | } 74 | return false 75 | }; 76 | ``` 77 | 78 | -------------------------------------------------------------------------------- /401-500/421.md: -------------------------------------------------------------------------------- 1 | ### 421. 数组中两个数的最大异或值 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`位运算`、`字典树` 6 | 7 | 给定一个非空数组,数组中元素为 a0, a1, a2, … , an-1,其中 0 ≤ ai < 231。 8 | 9 | 10 | 11 | 找到 ai 和aj最大的异或 (XOR) 运算结果,其中0 ≤ *i* ,*j* < *n* 。 12 | 13 | 14 | 15 | 你能在O(*n* )的时间解决这个问题吗? 16 | 17 | 18 | 19 | **示例:** 20 | 21 | 22 | 23 | ``` 24 | 25 | 输入: [3, 10, 5, 25, 2, 8] 26 | 27 | 输出: 28 28 | 29 | 解释: 最大的结果是 5 ^ 25 = 28. 30 | ``` 31 | 32 | ``` 33 | /** 34 | * @param {number[]} nums 35 | * @return {number} 36 | */ 37 | var findMaximumXOR = function(nums) { 38 | let max=Math.max.apply(Math,nums) 39 | let boundry=Math.pow(2,Math.floor(Math.log2(max))) 40 | let maxLenArr=[] 41 | for(let i=0;i=boundry)maxLenArr.push(cur) 44 | } 45 | let maxXOR=0 46 | for(let i=0;i0){ 48 | let len=arr.length 49 | let temp=[] 50 | for(let i=0;in) hi=mid-1 64 | else lo=mid 65 | } 66 | return lo 67 | } 68 | ``` 69 | 70 | -------------------------------------------------------------------------------- /401-500/442.md: -------------------------------------------------------------------------------- 1 | ### 442. 数组中重复的数据 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`数组` 6 | 7 | 给定一个整数数组 a,其中1 ≤ a[i] ≤ *n* (*n* 为数组长度), 其中有些元素出现**两次** 而其他元素出现**一次** 。 8 | 9 | 10 | 11 | 找到所有出现**两次** 的元素。 12 | 13 | 14 | 15 | 你可以不用到任何额外空间并在O(*n* )时间复杂度内解决这个问题吗? 16 | 17 | 18 | 19 | **示例:** 20 | 21 | 22 | 23 | ``` 24 | 25 | 输入: 26 | [4,3,2,7,8,2,3,1] 27 | 28 | 输出: 29 | [2,3] 30 | ``` 31 | 32 | ``` 33 | /** 34 | * @param {number[]} nums 35 | * @return {number[]} 36 | */ 37 | var findDuplicates = function(nums) { 38 | let res=[]; 39 | for(let i=0;i0){ 42 | nums[abs-1]*=-1 43 | }else{ 44 | res.push(abs) 45 | } 46 | } 47 | return res 48 | }; 49 | ``` 50 | 51 | -------------------------------------------------------------------------------- /401-500/448.md: -------------------------------------------------------------------------------- 1 | ### 448. 找到所有数组中消失的数字 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`数组` 6 | 7 | 给定一个范围在 1 ≤ a[i] ≤ *n* (*n* = 数组大小 ) 的 整型数组,数组中的元素一些出现了两次,另一些只出现一次。 8 | 9 | 10 | 11 | 找到所有在 [1, *n* ] 范围之间没有出现在数组中的数字。 12 | 13 | 14 | 15 | 您能在不使用额外空间且时间复杂度为*O(n)* 的情况下完成这个任务吗? 你可以假定返回的数组不算在额外空间内。 16 | 17 | 18 | 19 | **示例:** 20 | 21 | 22 | 23 | ``` 24 | 25 | 输入: 26 | [4,3,2,7,8,2,3,1] 27 | 28 | 输出: 29 | [5,6] 30 | ``` 31 | 32 | ``` 33 | /** 34 | * @param {number[]} nums 35 | * @return {number[]} 36 | */ 37 | var findDisappearedNumbers = function(nums) { 38 | // let arr=[] 39 | // for(let i=0;i0)arr.push(i+1) 47 | // } 48 | // return arr 49 | 50 | let arr=[]; 51 | let len=nums.length; 52 | for(let i=0;i [2,3,3] => [3,4,3] => [4,4,4] 27 | ``` 28 | 29 | ``` 30 | /** 31 | * @param {number[]} nums 32 | * @return {number} 33 | */ 34 | var minMoves = function(nums) { 35 | let sum=0 36 | for(let n of nums)sum+=n 37 | let min=Math.min.apply(Math,nums) 38 | return sum-min*nums.length 39 | }; 40 | ``` 41 | 42 | -------------------------------------------------------------------------------- /401-500/459.md: -------------------------------------------------------------------------------- 1 | ### 459. 重复的子字符串 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`字符串` 6 | 7 | 给定一个非空的字符串,判断它是否可以由它的一个子串重复多次构成。给定的字符串只含有小写英文字母,并且长度不超过10000。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | 14 | 15 | ``` 16 | 17 | 输入: "abab" 18 | 19 | 输出: True 20 | 21 | 解释: 可由子字符串 "ab" 重复两次构成。 22 | ``` 23 | 24 | 25 | **示例 2:** 26 | 27 | 28 | 29 | ``` 30 | 31 | 输入: "aba" 32 | 33 | 输出: False 34 | ``` 35 | 36 | 37 | **示例 3:** 38 | 39 | 40 | 41 | ``` 42 | 43 | 输入: "abcabcabcabc" 44 | 45 | 输出: True 46 | 47 | 解释: 可由子字符串 "abc" 重复四次构成。 (或者子字符串 "abcabc" 重复两次构成。) 48 | ``` 49 | 50 | ``` 51 | /** 52 | * @param {string} s 53 | * @return {boolean} 54 | */ 55 | var repeatedSubstringPattern = function(s) { 56 | let ss=(s+s).substring(1,s.length*2-1) 57 | return ss.includes(s) 58 | }; 59 | ``` 60 | 61 | -------------------------------------------------------------------------------- /401-500/461.md: -------------------------------------------------------------------------------- 1 | ### 461. 汉明距离 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`位运算` 6 | 7 | 两个整数之间的[汉明距离](https://baike.baidu.com/item/%E6%B1%89%E6%98%8E%E8%B7%9D%E7%A6%BB) 8 | 指的是这两个数字对应二进制位不同的位置的数目。 9 | 10 | 11 | 12 | 给出两个整数 `x` 和 `y` ,计算它们之间的汉明距离。 13 | 14 | 15 | 16 | **注意:** 17 | 0 ≤ `x` , `y` < 231. 18 | 19 | 20 | 21 | **示例:** 22 | 23 | 24 | 25 | ``` 26 | 27 | 输入: x = 1, y = 4 28 | 29 | 输出: 2 30 | 31 | 解释: 32 | 1 (0 0 0 1) 33 | 4 (0 1 0 0) 34 | ↑ ↑ 35 | 36 | 上面的箭头指出了对应二进制位不同的位置。 37 | ``` 38 | 39 | 40 | 41 | ----- 42 | 43 | 思路: 44 | 45 | 两个数(a,b)的海明距离就是`a^b`后存在`1`的数量。 46 | 47 | ``` 48 | /** 49 | * @param {number} x 50 | * @param {number} y 51 | * @return {number} 52 | */ 53 | var hammingDistance = function(x, y) { 54 | let xor=x^y 55 | let res=0 56 | while(xor>0){ 57 | if(xor % 2===1)res++ 58 | xor=xor>>1 59 | } 60 | return res 61 | }; 62 | ``` 63 | 64 | -------------------------------------------------------------------------------- /401-500/462.md: -------------------------------------------------------------------------------- 1 | ### 462. 最少移动次数使数组元素相等 II 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`数学` 6 | 7 | 给定一个非空整数数组,找到使所有数组元素相等所需的最小移动数,其中每次移动可将选定的一个元素加1或减1。 您可以假设数组的长度最多为10000。 8 | 9 | 10 | 11 | **例如:** 12 | 13 | 14 | 15 | ``` 16 | 17 | 输入: 18 | [1,2,3] 19 | 20 | 输出: 21 | 2 22 | 23 | 说明:只有两个动作是必要的(记得每一步仅可使其中一个元素加1或减1): 24 | 25 | [1,2,3] => [2,2,3] => [2,2,2] 26 | ``` 27 | 28 | ``` 29 | /** 30 | * @param {number[]} nums 31 | * @return {number} 32 | */ 33 | var minMoves2 = function(nums) { 34 | nums.sort((a,b)=>a-b) 35 | let allSteps=0 36 | let mid=nums[Math.floor(nums.length/2)] 37 | for(let i=0;imaxCount){ 45 | maxCount=curCount 46 | } 47 | curCount=0; 48 | continue; 49 | } 50 | curCount++; 51 | } 52 | return Math.max(maxCount,curCount) 53 | }; 54 | ``` 55 | 56 | -------------------------------------------------------------------------------- /401-500/492.md: -------------------------------------------------------------------------------- 1 | ### 492. 构造矩形 2 | 3 | 难度:Easy 4 | 5 | 相关话题: 6 | 7 | 作为一位web开发者, 懂得怎样去规划一个页面的尺寸是很重要的。 现给定一个具体的矩形页面面积,你的任务是设计一个长度为 L 和宽度为 W 且满足以下要求的矩形的页面。要求: 8 | 9 | 10 | 11 | ``` 12 | 13 | 1. 你设计的矩形页面必须等于给定的目标面积。 14 | 15 | 2. 宽度 W 不应大于长度 L,换言之,要求 L >= W 。 16 | 17 | 3. 长度 L 和宽度 W 之间的差距应当尽可能小。 18 | ``` 19 | 20 | 21 | 你需要按顺序输出你设计的页面的长度 L 和宽度 W。 22 | 23 | 24 | 25 | **示例:** 26 | 27 | 28 | 29 | ``` 30 | 31 | 输入: 4 32 | 输出: [2, 2] 33 | 解释: 目标面积是 4, 所有可能的构造方案有 [1,4], [2,2], [4,1]。 34 | 但是根据要求2,[1,4] 不符合要求; 根据要求3,[2,2] 比 [4,1] 更能符合要求. 所以输出长度 L 为 2, 宽度 W 为 2。 35 | ``` 36 | 37 | 38 | **说明:** 39 | 40 | 41 | 42 | 43 | 1. 给定的面积不大于 10,000,000 且为正整数。 44 | 45 | 2. 你设计的页面的长度和宽度必须都是正整数。 46 | 47 | 48 | 49 | 50 | 51 | 52 | ----- 53 | 54 | 思路: 55 | 56 | 因为`width`一定不大于`height`,因此`width`的最大值就是`Math.sqrt(area)`,遍历`width`递减到`1`,如果存在`area % i===0`,当前`i`就是结果`width`。 57 | 58 | ``` 59 | /** 60 | * @param {number} area 61 | * @return {number[]} 62 | */ 63 | var constructRectangle = function(area) { 64 | let maxWidth=Math.floor(Math.sqrt(area)) 65 | for(let i=maxWidth;i>=1;i--){ 66 | if(area % i===0)return [area/i,i] 67 | } 68 | }; 69 | ``` 70 | 71 | -------------------------------------------------------------------------------- /501-600/504.md: -------------------------------------------------------------------------------- 1 | ### 504. 七进制数 2 | 3 | 难度:Easy 4 | 5 | 相关话题: 6 | 7 | 给定一个整数,将其转化为7进制,并以字符串形式输出。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | 14 | 15 | ``` 16 | 17 | 输入: 100 18 | 输出: "202" 19 | ``` 20 | 21 | 22 | **示例 2:** 23 | 24 | 25 | 26 | ``` 27 | 28 | 输入: -7 29 | 输出: "-10" 30 | ``` 31 | 32 | 33 | **注意:** 输入范围是[-1e7, 1e7] 。 34 | 35 | 36 | 37 | 38 | ----- 39 | 40 | 思路: 41 | 42 | 先判断正负,然后对`num`的绝对值进行转换。 43 | 44 | ``` 45 | /** 46 | * @param {number} num 47 | * @return {string} 48 | */ 49 | var convertToBase7 = function(num) { 50 | let syb=num<0?'-':'' 51 | num=Math.abs(num) 52 | let str='' 53 | while(num>0){ 54 | str=(num % 7)+str 55 | num=Math.floor(num/7) 56 | } 57 | if(str==='')return '0' 58 | return syb+str 59 | }; 60 | ``` 61 | 62 | -------------------------------------------------------------------------------- /501-600/507.md: -------------------------------------------------------------------------------- 1 | ### 507. 完美数 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`数学` 6 | 7 | 对于一个**正整数** ,如果它和除了它自身以外的所有正因子之和相等,我们称它为“完美数”。 8 | 9 | 10 | 11 | 给定一个**正整数** `n` ,如果他是完美数,返回 `True` ,否则返回 `False` 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | **示例:** 20 | 21 | 22 | 23 | ``` 24 | 25 | 输入: 28 26 | 输出: True 27 | 解释: 28 = 1 + 2 + 4 + 7 + 14 28 | ``` 29 | 30 | 31 | 32 | 33 | 34 | 35 | **注意:** 36 | 37 | 38 | 39 | 输入的数字**`n`** 不会超过 100,000,000. (1e8) 40 | 41 | 42 | ``` 43 | /** 44 | * @param {number} num 45 | * @return {boolean} 46 | */ 47 | var checkPerfectNumber = function(num) { 48 | if(num===1)return false 49 | let sqrt=Math.floor(Math.sqrt(num)) 50 | let sum=1 51 | for(let i=2;i<=sqrt;i++){ 52 | if(num % i===0){ 53 | sum+=i 54 | sum+=num/i 55 | } 56 | } 57 | // console.log(sum) 58 | return sum===num 59 | }; 60 | ``` 61 | 62 | -------------------------------------------------------------------------------- /501-600/509.md: -------------------------------------------------------------------------------- 1 | ### 509. 斐波那契数 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`数组` 6 | 7 | **斐波那契数** ,通常用 `F(n)` 表示,形成的序列称为**斐波那契数列** 。该数列由 `0` 和 `1` 开始,后面的每一项数字都是前面两项数字的和。也就是: 8 | 9 | 10 | 11 | ``` 12 | F(0) = 0, F(1)= 1 13 | F(N) = F(N - 1) + F(N - 2), 其中 N > 1. 14 | ``` 15 | 16 | 17 | 给定 `N` ,计算 `F(N)` 。 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | **示例 1:** 26 | 27 | 28 | 29 | ``` 30 | 输入:2 31 | 输出:1 32 | 解释:F(2) = F(1) + F(0) = 1 + 0 = 1. 33 | ``` 34 | 35 | 36 | **示例 2:** 37 | 38 | 39 | 40 | ``` 41 | 输入:3 42 | 输出:2 43 | 解释:F(3) = F(2) + F(1) = 1 + 1 = 2. 44 | ``` 45 | 46 | 47 | **示例 3:** 48 | 49 | 50 | 51 | ``` 52 | 输入:4 53 | 输出:3 54 | 解释:F(4) = F(3) + F(2) = 2 + 1 = 3. 55 | ``` 56 | 57 | 58 | 59 | 60 | 61 | 62 | **提示:** 63 | 64 | 65 | 66 | 67 | * 0 ≤ `N` ≤ 30 68 | 69 | 70 | 71 | 72 | ``` 73 | /** 74 | * @param {number} N 75 | * @return {number} 76 | */ 77 | var fib = function(N) { 78 | let dp=[0,1] 79 | for(let i=2;i<=N;i++){ 80 | dp[i]=dp[i-1]+dp[i-2] 81 | } 82 | return dp[N] 83 | }; 84 | ``` 85 | 86 | -------------------------------------------------------------------------------- /501-600/515.md: -------------------------------------------------------------------------------- 1 | ### 515. 在每个树行中找最大值 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`树`、`深度优先搜索`、`广度优先搜索` 6 | 7 | 您需要在二叉树的每一行中找到最大的值。 8 | 9 | 10 | 11 | **示例:** 12 | 13 | 14 | 15 | ``` 16 | 17 | 输入: 18 | 19 | 1 20 | / \ 21 | 3 2 22 | / \ \ 23 | 5 3 9 24 | 25 | 输出: [1, 3, 9] 26 | ``` 27 | 28 | ``` 29 | /** 30 | * Definition for a binary tree node. 31 | * function TreeNode(val) { 32 | * this.val = val; 33 | * this.left = this.right = null; 34 | * } 35 | */ 36 | /** 37 | * @param {TreeNode} root 38 | * @return {number[]} 39 | */ 40 | var largestValues = function(root) { 41 | if(!root)return [] 42 | let ans=[] 43 | let arr=[root] 44 | while(arr.length>0){ 45 | let len=arr.length 46 | let maxV=-Infinity 47 | for(let i=0;iend)return 0 71 | if(start===end)return 1 72 | if(mem[start][end])return mem[start][end] 73 | let res 74 | if(str[start]===str[end]) res= lps(str,start+1,end-1)+2 75 | else res=Math.max(lps(str,start+1,end),lps(str,start,end-1)) 76 | mem[start][end]=res 77 | return res 78 | } 79 | }; 80 | ``` 81 | 82 | -------------------------------------------------------------------------------- /501-600/520.md: -------------------------------------------------------------------------------- 1 | ### 520. 检测大写字母 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`字符串` 6 | 7 | 给定一个单词,你需要判断单词的大写使用是否正确。 8 | 9 | 10 | 11 | 我们定义,在以下情况时,单词的大写用法是正确的: 12 | 13 | 14 | 15 | 16 | 1. 全部字母都是大写,比如"USA"。 17 | 18 | 2. 单词中所有字母都不是大写,比如"leetcode"。 19 | 20 | 3. 如果单词不只含有一个字母,只有首字母大写,比如"Google"。 21 | 22 | 23 | 24 | 25 | 26 | 否则,我们定义这个单词没有正确使用大写字母。 27 | 28 | 29 | 30 | **示例 1:** 31 | 32 | 33 | 34 | ``` 35 | 36 | 输入: "USA" 37 | 输出: True 38 | ``` 39 | 40 | 41 | **示例 2:** 42 | 43 | 44 | 45 | ``` 46 | 47 | 输入: "FlaG" 48 | 输出: False 49 | ``` 50 | 51 | 52 | **注意:** 输入是由大写和小写拉丁字母组成的非空单词。 53 | 54 | 55 | ``` 56 | /** 57 | * @param {string} word 58 | * @return {boolean} 59 | */ 60 | var detectCapitalUse = function(word) { 61 | if(word.length===1)return true 62 | let allUpp=word.charCodeAt(0)<97 && word.charCodeAt(1)<97 ? true : false 63 | return assert(word,allUpp) 64 | 65 | function assert(word,allUpp){ 66 | for(let i=1;i=97)return false 68 | else if(!allUpp && word.charCodeAt(i)<97)return false 69 | } 70 | return true 71 | } 72 | }; 73 | ``` 74 | 75 | -------------------------------------------------------------------------------- /501-600/521.md: -------------------------------------------------------------------------------- 1 | ### 521. 最长特殊序列 Ⅰ 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`字符串` 6 | 7 | 给定两个字符串,你需要从这两个字符串中找出最长的特殊序列。最长特殊序列定义如下:该序列为某字符串独有的最长子序列(即不能是其他字符串的子序列)。 8 | 9 | 10 | 11 | **子序列** 可以通过删去字符串中的某些字符实现,但不能改变剩余字符的相对顺序。空序列为所有字符串的子序列,任何字符串为其自身的子序列。 12 | 13 | 14 | 15 | 输入为两个字符串,输出最长特殊序列的长度。如果不存在,则返回 -1。 16 | 17 | 18 | 19 | **示例 :** 20 | 21 | 22 | 23 | ``` 24 | 输入: "aba", "cdc" 25 | 输出: 3 26 | 解析: 最长特殊序列可为 "aba" (或 "cdc") 27 | ``` 28 | 29 | 30 | **说明:** 31 | 32 | 33 | 34 | 35 | 1. 两个字符串长度均小于100。 36 | 37 | 2. 字符串中的字符仅含有'a'~'z'。 38 | 39 | 40 | 41 | 42 | ``` 43 | /** 44 | * @param {string} a 45 | * @param {string} b 46 | * @return {number} 47 | */ 48 | var findLUSlength = function(a, b) { 49 | let aLen=a.length; 50 | let bLen=b.length; 51 | if(aLen===0 && bLen===0 || a===b){ 52 | return -1 53 | }else if(aLen>bLen){ 54 | return aLen 55 | }else{ 56 | return bLen 57 | } 58 | }; 59 | ``` 60 | 61 | -------------------------------------------------------------------------------- /501-600/523.md: -------------------------------------------------------------------------------- 1 | ### 523. 连续的子数组和 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`数学`、`动态规划` 6 | 7 | 给定一个包含**非负数** 的数组和一个目标**整数** k,编写一个函数来判断该数组是否含有连续的子数组,其大小至少为 2,总和为 **k** 的倍数,即总和为 n*k,其中 n 也是一个**整数** 。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | 14 | 15 | ``` 16 | 输入: [23,2,4,6,7], k = 6 17 | 输出: True 18 | 解释: [2,4] 是一个大小为 2 的子数组,并且和为 6。 19 | ``` 20 | 21 | 22 | **示例 2:** 23 | 24 | 25 | 26 | ``` 27 | 输入: [23,2,6,4,7], k = 6 28 | 输出: True 29 | 解释: [23,2,6,4,7]是大小为 5 的子数组,并且和为 42。 30 | ``` 31 | 32 | 33 | **说明:** 34 | 35 | 36 | 37 | 38 | 1. 数组的长度不会超过10,000。 39 | 40 | 2. 你可以认为所有数字总和在 32 位有符号整数范围内。 41 | 42 | 43 | 44 | 45 | ``` 46 | /** 47 | * @param {number[]} nums 48 | * @param {number} k 49 | * @return {boolean} 50 | */ 51 | var checkSubarraySum = function(nums, k) { 52 | let sums=[] 53 | for(let i=0;i0?sums[i-1]:0) 55 | if(i>0 && ((sums[i] % k===0) || (sums[i]===k)))return true 56 | } 57 | 58 | if(k===0)return false 59 | let dp=[] 60 | for(let i=0;i1)return true 64 | }else{ 65 | dp[m]=i 66 | } 67 | } 68 | return false 69 | 70 | }; 71 | ``` 72 | 73 | -------------------------------------------------------------------------------- /501-600/525.md: -------------------------------------------------------------------------------- 1 | ### 525. 连续数组 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`哈希表` 6 | 7 | 给定一个二进制数组, 找到含有相同数量的 0 和 1 的最长连续子数组(的长度)。 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | **示例 1:** 16 | 17 | 18 | 19 | ``` 20 | 输入: [0,1] 21 | 输出: 2 22 | 说明: [0, 1] 是具有相同数量0和1的最长连续子数组。 23 | ``` 24 | 25 | 26 | **示例 2:** 27 | 28 | 29 | 30 | ``` 31 | 输入: [0,1,0] 32 | 输出: 2 33 | 说明: [0, 1] (或 [1, 0]) 是具有相同数量0和1的最长连续子数组。 34 | ``` 35 | 36 | 37 | 38 | 39 | 40 | 41 | **注意:** 给定的二进制数组的长度不会超过50000。 42 | 43 | 44 | 45 | 46 | ----- 47 | 48 | 思路: 49 | 50 | 假设给定一个数组`[0,1,0,0,0,1]`,他们的前缀和是`[0,1,1,1,1,2]` 51 | 52 | 这并不能看出什么有效的信息,但如果将`0`替换成`1`后,变为`[-1,1,-1,-1,-1,1]`,他们的前缀和是`[-1,0,-1,-2,-3,-2]` 53 | 54 | 可以看出,当存在相同的前缀和时,说明这是一个`0`和`1`都相等的子数组。 55 | 56 | ``` 57 | /** 58 | * @param {number[]} nums 59 | * @return {number} 60 | */ 61 | var findMaxLength = function(nums) { 62 | let aux=nums.map(n=>n===0?-1:1) 63 | let hash={0:-1},maxLen=0 64 | let sum=0 65 | for(let i=0;i=1){ 54 | for(let i=h;i=h && arr[j]max)max=count 62 | } 63 | return max 64 | }; 65 | ``` 66 | 67 | -------------------------------------------------------------------------------- /501-600/575.md: -------------------------------------------------------------------------------- 1 | ### 575. 分糖果 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`哈希表` 6 | 7 | 给定一个**偶数** 长度的数组,其中不同的数字代表着不同种类的糖果,每一个数字代表一个糖果。你需要把这些糖果**平均** 分给一个弟弟和一个妹妹。返回妹妹可以获得的最大糖果的种类数。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | 14 | 15 | ``` 16 | 17 | 输入: candies = [1,1,2,2,3,3] 18 | 输出: 3 19 | 解析:一共有三种种类的糖果,每一种都有两个。 20 | 最优分配方案:妹妹获得[1,2,3],弟弟也获得[1,2,3]。这样使妹妹获得糖果的种类数最多。 21 | ``` 22 | 23 | 24 | **示例 2 :** 25 | 26 | 27 | 28 | ``` 29 | 30 | 输入: candies = [1,1,2,3] 31 | 输出: 2 32 | 解析: 妹妹获得糖果[2,3],弟弟获得糖果[1,1],妹妹有两种不同的糖果,弟弟只有一种。这样使得妹妹可以获得的糖果种类数最多。 33 | ``` 34 | 35 | 36 | **注意:** 37 | 38 | 39 | 40 | 41 | 1. 数组的长度为[2, 10,000],并且确定为偶数。 42 | 43 | 1. 数组中数字的大小在范围[-100,000, 100,000]内。 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | ----- 56 | 57 | 思路: 58 | 59 | 先计算出所有糖果的种类`K`,两人平均分糖果,如果能分到的`len/2`小于`K`,那么只能选`len/2` 60 | 61 | 如果`len/2`大于`K`,那么就可以优先将所有种类糖果拿走,再补上缺少的,因此最终返回`Math.min(len/2,K)`。 62 | 63 | ``` 64 | /** 65 | * @param {number[]} candies 66 | * @return {number} 67 | */ 68 | var distributeCandies = function(candies) { 69 | let kinds=new Set(candies).size; 70 | return Math.min(candies.length/2,kinds) 71 | }; 72 | ``` 73 | 74 | -------------------------------------------------------------------------------- /501-600/581.md: -------------------------------------------------------------------------------- 1 | ### 581. 最短无序连续子数组 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`数组` 6 | 7 | 给定一个整数数组,你需要寻找一个**连续的子数组** ,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。 8 | 9 | 10 | 11 | 你找到的子数组应是**最短** 的,请输出它的长度。 12 | 13 | 14 | 15 | **示例 1:** 16 | 17 | 18 | 19 | ``` 20 | 21 | 输入: [2, 6, 4, 8, 10, 9, 15] 22 | 输出: 5 23 | 解释: 你只需要对 [6, 4, 8, 10, 9] 进行升序排序,那么整个表都会变为升序排序。 24 | ``` 25 | 26 | 27 | **说明 :** 28 | 29 | 30 | 31 | 32 | 1. 输入的数组长度范围在[1, 10,000]。 33 | 34 | 2. 输入的数组可能包含**重复** 元素,所以**升序** 的意思是**<=。** 35 | 36 | 37 | 38 | 39 | ``` 40 | /** 41 | * @param {number[]} nums 42 | * @return {number} 43 | */ 44 | var findUnsortedSubarray = function(nums) { 45 | let n = nums.length; 46 | let mx = nums[0]; 47 | let mn = nums[n-1]; 48 | let start = -1, end = -2; 49 | for(let i = 1; i < nums.length; i++){ 50 | mx = Math.max(mx, nums[i]); 51 | mn = Math.min(mn, nums[n-i-1]); 52 | if( mx > nums[i]) end = i; 53 | if(mn < nums[n-1-i]) start = n - 1 - i; 54 | } 55 | return end - start +1; 56 | }; 57 | ``` 58 | 59 | -------------------------------------------------------------------------------- /501-600/583.md: -------------------------------------------------------------------------------- 1 | ### 583. 两个字符串的删除操作 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`字符串` 6 | 7 | 给定两个单词*word1* 和*word2* ,找到使得*word1* 和*word2* 相同所需的最小步数,每步可以删除任意一个字符串中的一个字符。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | 14 | 15 | ``` 16 | 17 | 输入: "sea", "eat" 18 | 输出: 2 19 | 解释: 第一步将"sea"变为"ea",第二步将"eat"变为"ea" 20 | ``` 21 | 22 | 23 | **说明:** 24 | 25 | 26 | 27 | 28 | 1. 给定单词的长度不超过500。 29 | 30 | 2. 给定单词中的字符只含有小写字母。 31 | 32 | 33 | 34 | 35 | ``` 36 | /** 37 | * @param {string} word1 38 | * @param {string} word2 39 | * @return {number} 40 | */ 41 | var minDistance = function(a, b) { 42 | let aL=a.length,bL=b.length; 43 | let arr=[] 44 | for(let i=0;i<=aL;i++){ 45 | arr[i]=[] 46 | for(let j=0;j<=bL;j++){ 47 | arr[i][j]=0 48 | } 49 | } 50 | for(let i=1;i<=aL;i++){ 51 | for(let j=1;j<=bL;j++){ 52 | if(a[i-1]===b[j-1]){ 53 | arr[i][j]=arr[i-1][j-1]+1 54 | }else{ 55 | arr[i][j]=Math.max(arr[i-1][j],arr[i][j-1]) 56 | } 57 | } 58 | } 59 | 60 | return aL+bL-2*arr[aL][bL] 61 | }; 62 | ``` 63 | 64 | -------------------------------------------------------------------------------- /501-600/589.md: -------------------------------------------------------------------------------- 1 | ### 589. N叉树的前序遍历 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`树` 6 | 7 | 给定一个 N 叉树,返回其节点值的*前序遍历* 。 8 | 9 | 例如,给定一个 `3叉树` : 10 | 11 | 12 | 13 | ![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2018/10/12/narytreeexample.png) 14 | 15 | 16 | 17 | 18 | 返回其前序遍历: `[1,3,5,6,2,4]` 。 19 | 20 | 21 | 22 | **说明:** 递归法很简单,你可以使用迭代法完成此题吗? 23 | 24 | ``` 25 | /** 26 | * // Definition for a Node. 27 | * function Node(val,children) { 28 | * this.val = val; 29 | * this.children = children; 30 | * }; 31 | */ 32 | /** 33 | * @param {Node} root 34 | * @return {number[]} 35 | */ 36 | var preorder = function(root) { 37 | if(!root)return [] 38 | let stack=[root],res=[] 39 | while(stack.length>0 ){ 40 | let node=stack.pop() 41 | res.push(node.val) 42 | for(let i=node.children.length-1;i>=0;i--){ 43 | stack.push(node.children[i]) 44 | } 45 | } 46 | return res 47 | }; 48 | ``` 49 | 50 | -------------------------------------------------------------------------------- /501-600/590.md: -------------------------------------------------------------------------------- 1 | ### 590. N叉树的后序遍历 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`树` 6 | 7 | 给定一个 N 叉树,返回其节点值的*后序遍历* 。 8 | 9 | 例如,给定一个 `3叉树` : 10 | 11 | 12 | 13 | ![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2018/10/12/narytreeexample.png) 14 | 15 | 16 | 17 | 18 | 返回其后序遍历: `[5,6,3,2,4,1]` . 19 | 20 | 21 | 22 | **说明:** 递归法很简单,你可以使用迭代法完成此题吗? 23 | 24 | ``` 25 | /** 26 | * // Definition for a Node. 27 | * function Node(val,children) { 28 | * this.val = val; 29 | * this.children = children; 30 | * }; 31 | */ 32 | /** 33 | * @param {Node} root 34 | * @return {number[]} 35 | */ 36 | var postorder = function(root) { 37 | if(!root)return [] 38 | let stack=[root],res=[] 39 | while(stack.length>0 ){ 40 | let node=stack.pop() 41 | res.push(node.val) 42 | for(let i=0;i0)maxLen=Math.max(maxLen,hash[k]+hash[nxt]) 57 | } 58 | return maxLen 59 | }; 60 | ``` 61 | 62 | -------------------------------------------------------------------------------- /601-700/605.md: -------------------------------------------------------------------------------- 1 | ### 605. 种花问题 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`数组` 6 | 7 | 假设你有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花卉不能种植在相邻的地块上,它们会争夺水源,两者都会死去。 8 | 9 | 10 | 11 | 给定一个花坛(表示为一个数组包含0和1,其中0表示没种植花,1表示种植了花),和一个数**n** 。能否在不打破种植规则的情况下种入**n** 朵花?能则返回True,不能则返回False。 12 | 13 | 14 | 15 | **示例 1:** 16 | 17 | 18 | 19 | ``` 20 | 21 | 输入: flowerbed = [1,0,0,0,1], n = 1 22 | 输出: True 23 | ``` 24 | 25 | 26 | **示例 2:** 27 | 28 | 29 | 30 | ``` 31 | 32 | 输入: flowerbed = [1,0,0,0,1], n = 2 33 | 输出: False 34 | ``` 35 | 36 | 37 | **注意:** 38 | 39 | 40 | 41 | 42 | 1. 数组内已种好的花不会违反种植规则。 43 | 44 | 2. 输入的数组长度范围为 [1, 20000]。 45 | 46 | 3. **n** 是非负整数,且不会超过输入数组的大小。 47 | 48 | 49 | 50 | 51 | ``` 52 | /** 53 | * @param {number[]} flowerbed 54 | * @param {number} n 55 | * @return {boolean} 56 | */ 57 | var canPlaceFlowers = function(flowerbed, n) { 58 | if(n===0)return true 59 | 60 | for(let i=0;ia-b) 47 | for(let i=nums.length-1;i>=2;i--){ 48 | let l=0,r=i-1 49 | while(lnums[i]){ 51 | sum+=r-l 52 | r-- 53 | }else 54 | l++ 55 | } 56 | } 57 | return sum 58 | }; 59 | ``` 60 | 61 | -------------------------------------------------------------------------------- /601-700/621.md: -------------------------------------------------------------------------------- 1 | ### 621. 任务调度器 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`贪心算法`、`队列`、`数组` 6 | 7 | 给定一个用字符数组表示的 CPU 需要执行的任务列表。其中包含使用大写的 A - Z 字母表示的26 种不同种类的任务。任务可以以任意顺序执行,并且每个任务都可以在 1 个单位时间内执行完。CPU 在任何一个单位时间内都可以执行一个任务,或者在待命状态。 8 | 9 | 10 | 11 | 然而,两个**相同种类** 的任务之间必须有长度为**n** 的冷却时间,因此至少有连续 n 个单位时间内 CPU 在执行不同的任务,或者在待命状态。 12 | 13 | 14 | 15 | 你需要计算完成所有任务所需要的**最短时间** 。 16 | 17 | 18 | 19 | **示例 1:** 20 | 21 | 22 | 23 | ``` 24 | 25 | 输入: tasks = ["A","A","A","B","B","B"], n = 2 26 | 输出: 8 27 | 执行顺序: A -> B -> (待命) -> A -> B -> (待命) -> A -> B. 28 | ``` 29 | 30 | 31 | **注:** 32 | 33 | 34 | 35 | 36 | 1. 任务的总个数为[1, 10000]。 37 | 38 | 2. n 的取值范围为 [0, 100]。 39 | 40 | 41 | 42 | 43 | ``` 44 | /** 45 | * @param {character[]} tasks 46 | * @param {number} n 47 | * @return {number} 48 | */ 49 | var leastInterval = function(tasks, n) { 50 | let c = Array(26).fill(0) 51 | let acode='A'.charCodeAt(0) 52 | for(let t of tasks){ 53 | c[t.charCodeAt(0)-acode]++; 54 | } 55 | c.sort((a,b)=>a-b) 56 | let i = 25; 57 | while(i >= 0 && c[i] == c[25]) i--; 58 | 59 | return Math.max(tasks.length, (c[25] - 1) * (n + 1) + 25 - i); 60 | }; 61 | ``` 62 | 63 | -------------------------------------------------------------------------------- /601-700/628.md: -------------------------------------------------------------------------------- 1 | ### 628. 三个数的最大乘积 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`数组`、`数学` 6 | 7 | 给定一个整型数组,在数组中找出由三个数组成的最大乘积,并输出这个乘积。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | 14 | 15 | ``` 16 | 17 | 输入: [1,2,3] 18 | 输出: 6 19 | ``` 20 | 21 | 22 | **示例 2:** 23 | 24 | 25 | 26 | ``` 27 | 28 | 输入: [1,2,3,4] 29 | 输出: 24 30 | ``` 31 | 32 | 33 | **注意:** 34 | 35 | 36 | 37 | 38 | 1. 给定的整型数组长度范围是[3,104],数组中所有的元素范围是[-1000, 1000]。 39 | 40 | 2. 输入的数组中任意三个数的乘积不会超出32位有符号整数的范围。 41 | 42 | 43 | 44 | 45 | ``` 46 | /** 47 | * @param {number[]} nums 48 | * @return {number} 49 | */ 50 | var maximumProduct = function(nums) { 51 | nums.sort((a,b)=>b-a) 52 | let f=nums[0] 53 | 54 | if(f<0){ 55 | return f*nums[1]*nums[2] 56 | }else{ 57 | return f*Math.max(nums[1]*nums[2],nums[nums.length-1]*nums[nums.length-2]) 58 | } 59 | 60 | }; 61 | ``` 62 | 63 | -------------------------------------------------------------------------------- /601-700/633.md: -------------------------------------------------------------------------------- 1 | ### 633. 平方数之和 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`数学` 6 | 7 | 给定一个非负整数 `c` ,你要判断是否存在两个整数 `a` 和 `b` ,使得a2 + b2 = c。 8 | 9 | 10 | 11 | **示例1:** 12 | 13 | 14 | 15 | ``` 16 | 17 | 输入: 5 18 | 输出: True 19 | 解释: 1 * 1 + 2 * 2 = 5 20 | ``` 21 | 22 | 23 | 24 | 25 | 26 | 27 | **示例2:** 28 | 29 | 30 | 31 | ``` 32 | 33 | 输入: 3 34 | 输出: False 35 | ``` 36 | 37 | ``` 38 | /** 39 | * @param {number} c 40 | * @return {boolean} 41 | */ 42 | var judgeSquareSum = function(c) { 43 | let limit=Math.floor(Math.sqrt(c)) 44 | for(let i=0;i<=limit;i++){ 45 | let r=Math.sqrt(c-i*i) 46 | if(r===Math.floor(r))return true 47 | } 48 | return false 49 | }; 50 | ``` 51 | 52 | -------------------------------------------------------------------------------- /601-700/637.md: -------------------------------------------------------------------------------- 1 | ### 637. 二叉树的层平均值 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`树` 6 | 7 | 给定一个非空二叉树, 返回一个由每层节点平均值组成的数组. 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | 14 | 15 | ``` 16 | 输入: 17 | 3 18 | / \ 19 | 9 20 20 | / \ 21 | 15 7 22 | 输出: [3, 14.5, 11] 23 | 解释: 24 | 第0层的平均值是 3, 第1层是 14.5, 第2层是 11. 因此返回 [3, 14.5, 11]. 25 | ``` 26 | 27 | 28 | **注意:** 29 | 30 | 31 | 32 | 33 | 1. 节点值的范围在32位有符号整数范围内。 34 | 35 | 36 | 37 | 38 | ``` 39 | /** 40 | * Definition for a binary tree node. 41 | * function TreeNode(val) { 42 | * this.val = val; 43 | * this.left = this.right = null; 44 | * } 45 | */ 46 | /** 47 | * @param {TreeNode} root 48 | * @return {number[]} 49 | */ 50 | var averageOfLevels = function(root) { 51 | if(!root)return [] 52 | let res=[],arr=[root] 53 | while(arr.length>0){ 54 | let len=arr.length,sum=0 55 | for(let i=0;imaxAvg)maxAvg=curAvg 53 | } 54 | return maxAvg 55 | }; 56 | ``` 57 | 58 | -------------------------------------------------------------------------------- /601-700/645.md: -------------------------------------------------------------------------------- 1 | ### 645. 错误的集合 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`哈希表`、`数学` 6 | 7 | 集合 `S` 包含从1到 `n` 的整数。不幸的是,因为数据错误,导致集合里面某一个元素复制了成了集合里面的另外一个元素的值,导致集合丢失了一个整数并且有一个元素重复。 8 | 9 | 10 | 11 | 给定一个数组 `nums` 代表了集合 `S` 发生错误后的结果。你的任务是首先寻找到重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。 12 | 13 | 14 | 15 | **示例 1:** 16 | 17 | 18 | 19 | ``` 20 | 21 | 输入: nums = [1,2,2,4] 22 | 输出: [2,3] 23 | ``` 24 | 25 | 26 | **注意:** 27 | 28 | 29 | 30 | 31 | 1. 给定数组的长度范围是[2, 10000]。 32 | 33 | 2. 给定的数组是无序的。 34 | 35 | 36 | 37 | 38 | ``` 39 | /** 40 | * @param {number[]} nums 41 | * @return {number[]} 42 | */ 43 | var findErrorNums = function(nums) { 44 | let mem=Array(nums.length).fill(false), 45 | err=null 46 | for(let i=0;inums[i+1]){ 51 | if(nums[i+1]<(nums[i-1] || 0) && nums[i]>nums[i+2])return false 52 | correct++ 53 | } 54 | if(correct>1)return false 55 | } 56 | return true 57 | }; 58 | ``` 59 | 60 | -------------------------------------------------------------------------------- /601-700/670.md: -------------------------------------------------------------------------------- 1 | ### 670. 最大交换 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`数组`、`数学` 6 | 7 | 给定一个非负整数,你**至多** 可以交换一次数字中的任意两位。返回你能得到的最大值。 8 | 9 | 10 | 11 | **示例 1 :** 12 | 13 | 14 | 15 | ``` 16 | 17 | 输入: 2736 18 | 输出: 7236 19 | 解释: 交换数字2和数字7。 20 | ``` 21 | 22 | 23 | **示例 2 :** 24 | 25 | 26 | 27 | ``` 28 | 29 | 输入: 9973 30 | 输出: 9973 31 | 解释: 不需要交换。 32 | ``` 33 | 34 | 35 | **注意:** 36 | 37 | 38 | 39 | 40 | 1. 给定数字的范围是[0, 108] 41 | 42 | 43 | 44 | 45 | ``` 46 | /** 47 | * @param {number} num 48 | * @return {number} 49 | */ 50 | var maximumSwap = function(num) { 51 | let str=num+'' 52 | let max=num 53 | let maxNum='',maxID=str.length-1 54 | for(let i=str.length-1;i>=0;i--){ 55 | if(str[i]>maxNum){ 56 | maxNum=str[i] 57 | maxID=i 58 | }else if(str[i]min){ 65 | ans=Math.min(ans,root.val) 66 | }else{ 67 | if(root.left)dfs(root.left) 68 | if(root.right)dfs(root.right) 69 | } 70 | } 71 | dfs(root) 72 | return ans==Infinity?-1:ans 73 | }; 74 | ``` 75 | 76 | -------------------------------------------------------------------------------- /601-700/674.md: -------------------------------------------------------------------------------- 1 | ### 674. 最长连续递增序列 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`数组` 6 | 7 | 给定一个未经排序的整数数组,找到最长且**连续** 的的递增序列。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | 14 | 15 | ``` 16 | 17 | 输入: [1,3,5,4,7] 18 | 输出: 3 19 | 解释: 最长连续递增序列是 [1,3,5], 长度为3。 20 | 尽管 [1,3,5,7] 也是升序的子序列, 但它不是连续的,因为5和7在原数组里被4隔开。 21 | ``` 22 | 23 | 24 | **示例 2:** 25 | 26 | 27 | 28 | ``` 29 | 30 | 输入: [2,2,2,2,2] 31 | 输出: 1 32 | 解释: 最长连续递增序列是 [2], 长度为1。 33 | ``` 34 | 35 | 36 | **注意:** 数组长度不会超过10000。 37 | 38 | 39 | ``` 40 | /** 41 | * @param {number[]} nums 42 | * @return {number} 43 | */ 44 | var findLengthOfLCIS = function(nums) { 45 | if(nums.length===0)return 0 46 | let start=0,maxLen=0 47 | let i=1 48 | for(;imaxLen)maxLen=temp 52 | start=i 53 | } 54 | } 55 | let temp=i-start 56 | if(temp>maxLen)maxLen=temp 57 | return maxLen 58 | }; 59 | ``` 60 | 61 | -------------------------------------------------------------------------------- /601-700/680.md: -------------------------------------------------------------------------------- 1 | ### 680. 验证回文字符串 Ⅱ 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`字符串` 6 | 7 | 给定一个非空字符串 `s` ,**最多** 删除一个字符。判断是否能成为回文字符串。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | 14 | 15 | ``` 16 | 17 | 输入: "aba" 18 | 输出: True 19 | ``` 20 | 21 | 22 | **示例 2:** 23 | 24 | 25 | 26 | ``` 27 | 28 | 输入: "abca" 29 | 输出: True 30 | 解释: 你可以删除c字符。 31 | ``` 32 | 33 | 34 | **注意:** 35 | 36 | 37 | 38 | 39 | 1. 字符串只包含从 a-z 的小写字母。字符串的最大长度是50000。 40 | 41 | 42 | 43 | 44 | ``` 45 | /** 46 | * @param {string} s 47 | * @return {boolean} 48 | */ 49 | var validPalindrome = function(s) { 50 | let left=0,right=s.length-1 51 | while(left<=right){ 52 | if(s[left]!==s[right]){ 53 | return check(left+1,right) || check(left,right-1) 54 | } 55 | left++ 56 | right-- 57 | } 58 | return true 59 | function check(left,right){ 60 | while(left<=right){ 61 | if(s[left]!==s[right])return false 62 | left++ 63 | right-- 64 | } 65 | return true 66 | } 67 | 68 | }; 69 | ``` 70 | 71 | -------------------------------------------------------------------------------- /601-700/686.md: -------------------------------------------------------------------------------- 1 | ### 686. 重复叠加字符串匹配 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`字符串` 6 | 7 | 给定两个字符串 A 和 B, 寻找重复叠加字符串A的最小次数,使得字符串B成为叠加后的字符串A的子串,如果不存在则返回 -1。 8 | 9 | 10 | 11 | 举个例子,A = "abcd",B = "cdabcdab"。 12 | 13 | 14 | 15 | 答案为 3,因为 A 重复叠加三遍后为“abcdabcdabcd”,此时 B 是其子串;A 重复叠加两遍后为"abcdabcd",B 并不是其子串。 16 | 17 | 18 | 19 | **注意:** 20 | 21 | 22 | 23 | `A` 与 `B` 字符串的长度在1和10000区间范围内。 24 | 25 | 26 | ``` 27 | /** 28 | * @param {string} A 29 | * @param {string} B 30 | * @return {number} 31 | */ 32 | var repeatedStringMatch = function(A, B) { 33 | let s='' 34 | for(let i=1;s.length<=A.length+B.length;i++){ 35 | s+=A 36 | if(s.includes(B))return i 37 | } 38 | return -1 39 | }; 40 | ``` 41 | 42 | -------------------------------------------------------------------------------- /601-700/693.md: -------------------------------------------------------------------------------- 1 | ### 693. 交替位二进制数 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`位运算` 6 | 7 | 给定一个正整数,检查他是否为交替位二进制数:换句话说,就是他的二进制数相邻的两个位数永不相等。 8 | 9 | 10 | 11 | **示例 1:** 12 | 13 | 14 | 15 | ``` 16 | 17 | 输入: 5 18 | 输出: True 19 | 解释: 20 | 5的二进制数是: 101 21 | ``` 22 | 23 | 24 | **示例 2:** 25 | 26 | 27 | 28 | ``` 29 | 30 | 输入: 7 31 | 输出: False 32 | 解释: 33 | 7的二进制数是: 111 34 | ``` 35 | 36 | 37 | **示例3:** 38 | 39 | 40 | 41 | ``` 42 | 43 | 输入: 11 44 | 输出: False 45 | 解释: 46 | 11的二进制数是: 1011 47 | ``` 48 | 49 | 50 | **示例 4:** 51 | 52 | 53 | 54 | ``` 55 | 56 | 输入: 10 57 | 输出: True 58 | 解释: 59 | 10的二进制数是: 1010 60 | ``` 61 | 62 | 63 | 64 | ----- 65 | 66 | 思路: 67 | 68 | 将数字转换为二进制的过程中,不断检查当前位的数字是否和上一位相反。 69 | 70 | ``` 71 | /** 72 | * @param {number} n 73 | * @return {boolean} 74 | */ 75 | var hasAlternatingBits = function(n) { 76 | let last; 77 | while(n>0){ 78 | let cur=n%2 79 | if(last!==cur){ 80 | last=cur 81 | }else{ 82 | return false 83 | } 84 | n=n>>1 85 | } 86 | return true 87 | }; 88 | ``` 89 | 90 | -------------------------------------------------------------------------------- /701-800/700.md: -------------------------------------------------------------------------------- 1 | ### 700. 二叉搜索树中的搜索 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`树` 6 | 7 | 给定二叉搜索树(BST)的根节点和一个值。 你需要在BST中找到节点值等于给定值的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 NULL。 8 | 9 | 10 | 11 | 例如, 12 | 13 | 14 | 15 | ``` 16 | 17 | 给定二叉搜索树: 18 | 19 | 4 20 | / \ 21 | 2 7 22 | / \ 23 | 1 3 24 | 25 | 和值: 2 26 | ``` 27 | 28 | 29 | 你应该返回如下子树: 30 | 31 | 32 | 33 | ``` 34 | 35 | 2 36 | / \ 37 | 1 3 38 | ``` 39 | 40 | 41 | 在上述示例中,如果要找的值是 `5` ,但因为没有节点值为 `5` ,我们应该返回 `NULL` 。 42 | 43 | 44 | ``` 45 | /** 46 | * Definition for a binary tree node. 47 | * function TreeNode(val) { 48 | * this.val = val; 49 | * this.left = this.right = null; 50 | * } 51 | */ 52 | /** 53 | * @param {TreeNode} root 54 | * @param {number} val 55 | * @return {TreeNode} 56 | */ 57 | var searchBST = function(root, val) { 58 | if(!root) return null 59 | if(root.val===val) return root 60 | if(root.val val ) return searchBST(root.left,val) 62 | }; 63 | ``` 64 | 65 | -------------------------------------------------------------------------------- /701-800/704.md: -------------------------------------------------------------------------------- 1 | ### 704. 二分查找 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`二分查找` 6 | 7 | 给定一个 `n` 个元素有序的(升序)整型数组 `nums` 和一个目标值 `target` ,写一个函数搜索 `nums` 中的 `target` ,如果目标值存在返回下标,否则返回 `-1` 。 8 | 9 | 10 | 11 | 12 | **示例 1:** 13 | 14 | 15 | 16 | ``` 17 | 输入: nums = [-1,0,3,5,9,12], target = 9 18 | 输出: 4 19 | 解释: 9 出现在 nums 中并且下标为 4 20 | ``` 21 | 22 | 23 | **示例2:** 24 | 25 | 26 | 27 | ``` 28 | 输入: nums = [-1,0,3,5,9,12], target = 2 29 | 输出: -1 30 | 解释: 2 不存在 nums 中因此返回 -1 31 | ``` 32 | 33 | 34 | 35 | 36 | 37 | 38 | **提示:** 39 | 40 | 41 | 42 | 43 | 1. 你可以假设 `nums` 中的所有元素是不重复的。 44 | 45 | 2. `n` 将在 `[1, 10000]` 之间。 46 | 47 | 3. `nums` 的每个元素都将在 `[-9999, 9999]` 之间。 48 | 49 | 50 | 51 | 52 | ``` 53 | /** 54 | * @param {number[]} nums 55 | * @param {number} target 56 | * @return {number} 57 | */ 58 | var search = function(nums, target) { 59 | let lo=0,hi=nums.length 60 | while(lotarget) hi=mid 64 | else return mid 65 | } 66 | return -1 67 | }; 68 | ``` 69 | 70 | -------------------------------------------------------------------------------- /701-800/709.md: -------------------------------------------------------------------------------- 1 | ### 709. 转换成小写字母 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`字符串` 6 | 7 | 实现函数 ToLowerCase(),该函数接收一个字符串参数 str,并将该字符串中的大写字母转换成小写字母,之后返回新的字符串。 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | **示例 1:** 16 | 17 | 18 | 19 | ``` 20 | 21 | 输入:"Hello" 22 | 输出:"hello" 23 | ``` 24 | 25 | 26 | **示例 2:** 27 | 28 | 29 | 30 | ``` 31 | 32 | 输入:"here" 33 | 输出:"here" 34 | ``` 35 | 36 | 37 | **示例** **3:** 38 | 39 | 40 | 41 | ``` 42 | 43 | 输入:"LOVELY" 44 | 输出:"lovely" 45 | ``` 46 | 47 | ``` 48 | /** 49 | * @param {string} str 50 | * @return {string} 51 | */ 52 | var toLowerCase = function(str) { 53 | let news='' 54 | for(let i=0;i=65 && c<=90){ 57 | news+=String.fromCharCode(c-65+97) 58 | }else{ 59 | news+=str[i] 60 | } 61 | } 62 | return news 63 | }; 64 | ``` 65 | 66 | -------------------------------------------------------------------------------- /701-800/713.md: -------------------------------------------------------------------------------- 1 | ### 713. 乘积小于K的子数组 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`数组`、`双指针` 6 | 7 | 给定一个正整数数组 `nums` 。 8 | 9 | 10 | 11 | 找出该数组内乘积小于 `k` 的连续的子数组的个数。 12 | 13 | 14 | 15 | **示例 1:** 16 | 17 | 18 | 19 | ``` 20 | 21 | 输入: nums = [10,5,2,6], k = 100 22 | 输出: 8 23 | 解释: 8个乘积小于100的子数组分别为: [10], [5], [2], [6], [10,5], [5,2], [2,6], [5,2,6]。 24 | 需要注意的是 [10,5,2] 并不是乘积小于100的子数组。 25 | ``` 26 | 27 | 28 | **说明:** 29 | 30 | 31 | 32 | 33 | * `0 < nums.length <= 50000` 34 | 35 | * `0 < nums[i] < 1000` 36 | 37 | * `0 <= k < 10^6` 38 | 39 | 40 | 41 | 42 | ``` 43 | /** 44 | * @param {number[]} nums 45 | * @param {number} k 46 | * @return {number} 47 | */ 48 | var numSubarrayProductLessThanK = function(nums, k) { 49 | let sum=1,res=0 50 | let left=0,right=0 51 | while(right=k){ 55 | sum=sum/nums[left++] 56 | } 57 | right++ 58 | res+=right-left 59 | } 60 | return res 61 | }; 62 | ``` 63 | 64 | -------------------------------------------------------------------------------- /701-800/717.md: -------------------------------------------------------------------------------- 1 | ### 717. 1比特与2比特字符 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`数组` 6 | 7 | 有两种特殊字符。第一种字符可以用一比特 `0` 来表示。第二种字符可以用两比特( `10` 或 `11` )来表示。 8 | 9 | 10 | 11 | 现给一个由若干比特组成的字符串。问最后一个字符是否必定为一个一比特字符。给定的字符串总是由0结束。 12 | 13 | 14 | 15 | **示例1:** 16 | 17 | 18 | 19 | ``` 20 | 21 | 输入: 22 | bits = [1, 0, 0] 23 | 输出: True 24 | 解释: 25 | 唯一的编码方式是一个两比特字符和一个一比特字符。所以最后一个字符是一比特字符。 26 | ``` 27 | 28 | 29 | **示例2:** 30 | 31 | 32 | 33 | ``` 34 | 35 | 输入: 36 | bits = [1, 1, 1, 0] 37 | 输出: False 38 | 解释: 39 | 唯一的编码方式是两比特字符和两比特字符。所以最后一个字符不是一比特字符。 40 | ``` 41 | 42 | 43 | **注意:** 44 | 45 | 46 | 47 | 48 | * `1 <= len(bits) <= 1000` . 49 | 50 | * `bits[i]` 总是 `0` 或 `1` . 51 | 52 | 53 | 54 | 55 | ``` 56 | /** 57 | * @param {number[]} bits 58 | * @return {boolean} 59 | */ 60 | var isOneBitCharacter = function(bits) { 61 | let len=bits.length 62 | for(let i=0;i0 && prevStr[prevStr.length-1]>S[i]){ 68 | prevStr=monotoneIncreasingDigits(+prevStr-1)+"9".repeat(S.length-i) 69 | break 70 | } 71 | prevStr+=S[i] 72 | } 73 | return +prevStr 74 | }; 75 | ``` 76 | 77 | -------------------------------------------------------------------------------- /701-800/739.md: -------------------------------------------------------------------------------- 1 | ### 739. 每日温度 2 | 3 | 难度:Middle 4 | 5 | 相关话题:`栈`、`哈希表` 6 | 7 | 根据每日 `气温` 列表,请重新生成一个列表,对应位置的输入是你需要再等待多久温度才会升高的天数。如果之后都不会升高,请输入 `0` 来代替。 8 | 9 | 10 | 11 | 例如,给定一个列表 `temperatures = [73, 74, 75, 71, 69, 72, 76, 73]` ,你的输出应该是 `[1, 1, 4, 2, 1, 1, 0, 0]` 。 12 | 13 | 14 | 15 | **提示:** `气温` 列表长度的范围是 `[1, 30000]` 。每个气温的值的都是 `[30, 100]` 范围内的整数。 16 | 17 | 18 | 19 | 20 | ----- 21 | 22 | 思路: 23 | 24 | 建立单调递增`stack`。 25 | 26 | 对`T`进行反向遍历(正向也可以),对内部每一个`T[i]`建立一个单调递增的`stack`,`stack`内部存放`T`的索引。 27 | 28 | 如果发现不是递增状态,通过`stack.pop()`调整,将离当前`T[i]`和离它最近的`stack[stack.length-1]`的差值添加进`res`。 29 | 30 | 31 | ``` 32 | /** 33 | * @param {number[]} T 34 | * @return {number[]} 35 | */ 36 | var dailyTemperatures = function(T) { 37 | let stack=[] 38 | let res=[] 39 | for(let i=T.length-1;i>=0;i--){ 40 | while(stack.length>0 && T[i]>=T[stack[stack.length-1]]){ 41 | stack.pop() 42 | } 43 | if(stack.length===0)res.push(0) 44 | else res.push(stack[stack.length-1]-i) 45 | stack.push(i) 46 | } 47 | return res.reverse() 48 | }; 49 | ``` 50 | 51 | -------------------------------------------------------------------------------- /701-800/754.md: -------------------------------------------------------------------------------- 1 | ### 754. 到达终点数字 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`数学` 6 | 7 | 在一根无限长的数轴上,你站在 `0` 的位置。终点在 `target` 的位置。 8 | 9 | 10 | 11 | 每次你可以选择向左或向右移动。第 n 次移动(从 1 开始),可以走 n 步。 12 | 13 | 14 | 15 | 返回到达终点需要的最小移动次数。 16 | 17 | 18 | 19 | **示例 1:** 20 | 21 | 22 | 23 | ``` 24 | 25 | 输入: target = 3 26 | 输出: 2 27 | 解释: 28 | 第一次移动,从 0 到 1 。 29 | 第二次移动,从 1 到 3 。 30 | ``` 31 | 32 | 33 | **示例 2:** 34 | 35 | 36 | 37 | ``` 38 | 39 | 输入: target = 2 40 | 输出: 3 41 | 解释: 42 | 第一次移动,从 0 到 1 。 43 | 第二次移动,从 1 到 -1 。 44 | 第三次移动,从 -1 到 2 。 45 | ``` 46 | 47 | 48 | **注意:** 49 | 50 | 51 | 52 | 53 | * `target` 是在 `[-10^9, 10^9]` 范围中的非零整数。 54 | 55 | 56 | 57 | 58 | ``` 59 | /** 60 | * @param {number} target 61 | * @return {number} 62 | */ 63 | var reachNumber = function(target) { 64 | target=Math.abs(target) 65 | let i=0,s=0 66 | for(;i/2*(i+1)1 21 | | | 22 | v v 23 | 2--->3 24 | 这有两条路: 0 -> 1 -> 3 和 0 -> 2 -> 3. 25 | ``` 26 | 27 | 28 | **提示:** 29 | 30 | 31 | 32 | 33 | * 结点的数量会在范围 `[2, 15]` 内。 34 | 35 | * 你可以把路径以任意顺序输出,但在路径内的结点的顺序必须保证。 36 | 37 | 38 | 39 | 40 | 41 | 42 | ----- 43 | 44 | 思路: 45 | 46 | `dfs`遍历,使用一个数组`stack`保存当前`dfs`的路径。 47 | 48 | ``` 49 | /** 50 | * @param {number[][]} graph 51 | * @return {number[][]} 52 | */ 53 | var allPathsSourceTarget = function(graph) { 54 | let n=graph.length 55 | let res=[] 56 | function dfs(v,stack){ 57 | if(v===n-1){ 58 | return res.push(stack.slice()) 59 | } 60 | let adj=graph[v] 61 | for(let i=0;i=0;i--){ 59 | if(S[i]===C)prev=i 60 | res[i]=Math.min(res[i],prev-i) 61 | } 62 | return res 63 | }; 64 | ``` 65 | 66 | -------------------------------------------------------------------------------- /801-900/830.md: -------------------------------------------------------------------------------- 1 | ### 830. 较大分组的位置 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`数组` 6 | 7 | 在一个由小写字母构成的字符串 `S` 中,包含由一些连续的相同字符所构成的分组。 8 | 9 | 10 | 11 | 例如,在字符串 `S = "abbxxxxzyy"` 中,就含有 `"a"` , `"bb"` , `"xxxx"` , `"z"` 和 `"yy"` 这样的一些分组。 12 | 13 | 14 | 15 | 我们称所有包含大于或等于三个连续字符的分组为较大分组。找到每一个较大分组的起始和终止位置。 16 | 17 | 18 | 19 | 最终结果按照字典顺序输出。 20 | 21 | 22 | 23 | **示例1:** 24 | 25 | 26 | 27 | ``` 28 | 29 | 输入:"abbxxxxzzy" 30 | 输出:[[3,6]] 31 | 解释: "xxxx" 是一个起始于 3 且终止于 6 的较大分组。 32 | ``` 33 | 34 | 35 | **示例 2:** 36 | 37 | 38 | 39 | ``` 40 | 41 | 输入:"abc" 42 | 输出:[] 43 | 解释: "a","b" 和 "c" 均不是符合要求的较大分组。 44 | ``` 45 | 46 | 47 | **示例 3:** 48 | 49 | 50 | 51 | ``` 52 | 53 | 输入:"abcdddeeeeaabbbcd" 54 | 输出:[[3,5],[6,9],[12,14]] 55 | ``` 56 | 57 | 58 | **说明:** `1 <= S.length <= 1000` 59 | 60 | 61 | ``` 62 | /** 63 | * @param {string} S 64 | * @return {number[][]} 65 | */ 66 | var largeGroupPositions = function(S) { 67 | let start=0,res=[] 68 | for(let i=0;i2)res.push([start,i-1]) 72 | start=i 73 | } 74 | } 75 | if(S.length-start>2)res.push([start,S.length-1]) 76 | return res 77 | }; 78 | ``` 79 | 80 | -------------------------------------------------------------------------------- /801-900/836.md: -------------------------------------------------------------------------------- 1 | ### 836. 矩形重叠 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`数学` 6 | 7 | 矩形以列表 `[x1, y1, x2, y2]` 的形式表示,其中 `(x1, y1)` 为左下角的坐标, `(x2, y2)` 是右上角的坐标。 8 | 9 | 10 | 11 | 如果相交的面积为正,则称两矩形重叠。需要明确的是,只在角或边接触的两个矩形不构成重叠。 12 | 13 | 14 | 15 | 给出两个矩形,判断它们是否重叠并返回结果。 16 | 17 | 18 | 19 | **示例 1:** 20 | 21 | 22 | 23 | ``` 24 | 输入:rec1 = [0,0,2,2], rec2 = [1,1,3,3] 25 | 输出:true 26 | ``` 27 | 28 | 29 | **示例 2:** 30 | 31 | 32 | 33 | ``` 34 | 输入:rec1 = [0,0,1,1], rec2 = [1,0,2,1] 35 | 输出:false 36 | ``` 37 | 38 | 39 | **说明:** 40 | 41 | 42 | 43 | 44 | 1. 两个矩形 `rec1` 和 `rec2` 都以含有四个整数的列表的形式给出。 45 | 46 | 2. 矩形中的所有坐标都处于 `-10^9` 和 `10^9` 之间。 47 | 48 | 49 | 50 | 51 | 52 | 53 | ----- 54 | 55 | 思路: 56 | 57 | 先算出这两个矩形有可能存在的交叉点,然后再判断这个交叉点是否有效的交叉点。 58 | 59 | ``` 60 | /** 61 | * @param {number[]} rec1 62 | * @param {number[]} rec2 63 | * @return {boolean} 64 | */ 65 | var isRectangleOverlap = function(rec1, rec2) { 66 | let x1 = rec1[0], y1 = rec1[1], x2 = rec1[2], y2 = rec1[3]; 67 | let x3 = rec2[0], y3 = rec2[1], x4 = rec2[2], y4 = rec2[3]; 68 | return (x1 < x4 && x3 < x2 && y1 < y4 && y3 < y2); 69 | }; 70 | ``` 71 | 72 | -------------------------------------------------------------------------------- /801-900/852.md: -------------------------------------------------------------------------------- 1 | ### 852. 山脉数组的峰顶索引 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`二分查找` 6 | 7 | 我们把符合下列属性的数组 `A` 称作山脉: 8 | 9 | 10 | 11 | 12 | * `A.length >= 3` 13 | 14 | * 存在 `0 < i< A.length - 1` 使得 `A[0] < A[1] < ... A[i-1] < A[i] > A[i+1] > ... > A[A.length - 1]` 15 | 16 | 17 | 18 | 19 | 20 | 给定一个确定为山脉的数组,返回任何满足 `A[0] < A[1] < ... A[i-1] < A[i] > A[i+1] > ... > A[A.length - 1]` 的 `i` 的值。 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | **示例 1:** 29 | 30 | 31 | 32 | ``` 33 | 输入:[0,1,0] 34 | 输出:1 35 | ``` 36 | 37 | 38 | **示例 2:** 39 | 40 | 41 | 42 | ``` 43 | 输入:[0,2,1,0] 44 | 输出:1 45 | ``` 46 | 47 | 48 | 49 | 50 | 51 | 52 | **提示:** 53 | 54 | 55 | 56 | 57 | 1. `3 <= A.length <= 10000` 58 | 59 | 2. 0 <= A[i] <= 10^6 60 | 61 | 3. A 是如上定义的山脉 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | ``` 71 | /** 72 | * @param {number[]} A 73 | * @return {number} 74 | */ 75 | var peakIndexInMountainArray = function(A) { 76 | return A.findIndex(n=>n===Math.max.apply(this,A)) 77 | }; 78 | ``` 79 | 80 | -------------------------------------------------------------------------------- /801-900/867.md: -------------------------------------------------------------------------------- 1 | ### 867. 转置矩阵 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`数组` 6 | 7 | 给定一个矩阵 `A` ,返回 `A` 的转置矩阵。 8 | 9 | 10 | 11 | 矩阵的转置是指将矩阵的主对角线翻转,交换矩阵的行索引与列索引。 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | **示例 1:** 20 | 21 | 22 | 23 | ``` 24 | 输入:[[1,2,3],[4,5,6],[7,8,9]] 25 | 输出:[[1,4,7],[2,5,8],[3,6,9]] 26 | ``` 27 | 28 | 29 | **示例 2:** 30 | 31 | 32 | 33 | ``` 34 | 输入:[[1,2,3],[4,5,6]] 35 | 输出:[[1,4],[2,5],[3,6]] 36 | ``` 37 | 38 | 39 | 40 | 41 | 42 | 43 | **提示:** 44 | 45 | 46 | 47 | 48 | 1. `1 <= A.length<= 1000` 49 | 50 | 2. `1 <= A[0].length<= 1000` 51 | 52 | 53 | 54 | 55 | ``` 56 | /** 57 | * @param {number[][]} A 58 | * @return {number[][]} 59 | */ 60 | var transpose = function(A) { 61 | let m=A.length,n=A[0].length 62 | let res=Array(n).fill().map(()=>Array(m).fill(0)) 63 | for(let i=0;i B[i]` 的索引 `i` 的数目来描述。 8 | 9 | 10 | 11 | 返回 `A` 的**任意** 排列,使其相对于 `B` 的优势最大化。 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | **示例 1:** 20 | 21 | 22 | 23 | ``` 24 | 输入:A = [2,7,11,15], B = [1,10,4,11] 25 | 输出:[2,11,7,15] 26 | ``` 27 | 28 | 29 | **示例 2:** 30 | 31 | 32 | 33 | ``` 34 | 输入:A = [12,24,8,32], B = [13,25,32,11] 35 | 输出:[24,32,8,12] 36 | ``` 37 | 38 | 39 | 40 | 41 | 42 | 43 | **提示:** 44 | 45 | 46 | 47 | 48 | 1. `1 <= A.length = B.length <= 10000` 49 | 50 | 2. `0 <= A[i] <= 10^9` 51 | 52 | 3. `0 <= B[i] <= 10^9` 53 | 54 | 55 | 56 | 57 | ``` 58 | /** 59 | * @param {number[]} A 60 | * @param {number[]} B 61 | * @return {number[]} 62 | */ 63 | var advantageCount = function(A, B) { 64 | A.sort((a,b)=>a-b) 65 | let sortedB=B.map((n,i)=>i).sort((a,b)=>B[b]-B[a]) 66 | let res=[] 67 | let minID=0,maxID=A.length-1 68 | for(let i=0;ival){ 72 | res[id]=A[maxID--] 73 | }else{ 74 | res[id]=A[minID++] 75 | } 76 | } 77 | return res 78 | }; 79 | ``` 80 | 81 | -------------------------------------------------------------------------------- /901-1000/905.md: -------------------------------------------------------------------------------- 1 | ### 905. 按奇偶排序数组 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`数组` 6 | 7 | 给定一个非负整数数组 `A` ,返回一个数组,在该数组中, `A` 的所有偶数元素之后跟着所有奇数元素。 8 | 9 | 10 | 11 | 你可以返回满足此条件的任何数组作为答案。 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | **示例:** 20 | 21 | 22 | 23 | ``` 24 | 输入:[3,1,2,4] 25 | 输出:[2,4,3,1] 26 | 输出 [4,2,3,1],[2,4,1,3] 和 [4,2,1,3] 也会被接受。 27 | ``` 28 | 29 | 30 | 31 | 32 | 33 | 34 | **提示:** 35 | 36 | 37 | 38 | 39 | 1. `1 <= A.length <= 5000` 40 | 41 | 2. `0 <= A[i] <= 5000` 42 | 43 | 44 | 45 | 46 | ``` 47 | /** 48 | * @param {number[]} A 49 | * @return {number[]} 50 | */ 51 | var sortArrayByParity = function(A) { 52 | let res=[] 53 | for(let i=0;i=j)return 68 | let p=nums[j],l=i,r=j-1 69 | while(l<=r){ 70 | while(l<=r && nums[l]p)r-- 72 | if(l>r)break 73 | swap(nums,l++,r--) 74 | } 75 | swap(nums,l,j) 76 | partition(i,l-1) 77 | partition(l+1,j) 78 | } 79 | function swap(arr,i,j){ 80 | let t=arr[i] 81 | arr[i]=arr[j] 82 | arr[j]=t 83 | } 84 | }; 85 | ``` 86 | 87 | -------------------------------------------------------------------------------- /901-1000/917.md: -------------------------------------------------------------------------------- 1 | ### 917. 仅仅反转字母 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`字符串` 6 | 7 | 给定一个字符串 `S` ,返回“反转后的”字符串,其中不是字母的字符都保留在原地,而所有字母的位置发生反转。 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | **示例 1:** 21 | 22 | 23 | 24 | ``` 25 | 输入:"ab-cd" 26 | 输出:"dc-ba" 27 | ``` 28 | 29 | 30 | **示例 2:** 31 | 32 | 33 | 34 | ``` 35 | 输入:"a-bC-dEf-ghIj" 36 | 输出:"j-Ih-gfE-dCba" 37 | ``` 38 | 39 | 40 | **示例 3:** 41 | 42 | 43 | 44 | ``` 45 | 输入:"Test1ng-Leet=code-Q!" 46 | 输出:"Qedo1ct-eeLg=ntse-T!" 47 | ``` 48 | 49 | 50 | 51 | 52 | 53 | 54 | **提示:** 55 | 56 | 57 | 58 | 59 | 1. `S.length <= 100` 60 | 61 | 2. `33 <= S[i].ASCIIcode <= 122` 62 | 63 | 3. `S` 中不包含 `\` or `"` 64 | 65 | 66 | 67 | 68 | ``` 69 | /** 70 | * @param {string} S 71 | * @return {string} 72 | */ 73 | var reverseOnlyLetters = function(S) { 74 | let rs='' 75 | for(let i=S.length-1;i>=0;i--){ 76 | if(/[a-zA-Z]/.test(S[i]))rs+=S[i] 77 | } 78 | let result='',j=0 79 | for(let i=0;i=S`, 56 | 说明有可能存在一组连续的子数组的和为`S`,这时检查`hash[preSum-S]`,如果发现存在, 57 | 说明之前存在`hash[preSum-S]`个位置,与当前位置的差值为`S`。 58 | 59 | ``` 60 | /** 61 | * @param {number[]} A 62 | * @param {number} S 63 | * @return {number} 64 | */ 65 | var numSubarraysWithSum = function(A, S) { 66 | let hash=[1],preSum=0,result=0 67 | for(let i=0;i=S)result+=hash[preSum-S] || 0 70 | if(!hash[preSum])hash[preSum]=1 71 | else hash[preSum]++ 72 | } 73 | return result 74 | }; 75 | ``` 76 | 77 | -------------------------------------------------------------------------------- /901-1000/942.md: -------------------------------------------------------------------------------- 1 | ### 942. 增减字符串匹配 2 | 3 | 难度:Easy 4 | 5 | 相关话题:`数学` 6 | 7 | 给定只含 `"I"` (增大)或 `"D"` (减小)的字符串 `S` ,令 `N = S.length` 。 8 | 9 | 10 | 11 | 返回 `[0, 1, ..., N]` 的任意排列 `A` 使得对于所有 `i = 0,..., N-1` ,都有: 12 | 13 | 14 | 15 | 16 | * 如果 `S[i] == "I"` ,那么 `A[i] < A[i+1]` 17 | 18 | * 如果 `S[i] == "D"` ,那么 `A[i] > A[i+1]` 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | **示例 1:** 29 | 30 | 31 | 32 | ``` 33 | 输出:"IDID" 34 | 输出:[0,4,1,3,2] 35 | ``` 36 | 37 | 38 | **示例 2:** 39 | 40 | 41 | 42 | ``` 43 | 输出:"III" 44 | 输出:[0,1,2,3] 45 | ``` 46 | 47 | 48 | **示例 3:** 49 | 50 | 51 | 52 | ``` 53 | 输出:"DDI" 54 | 输出:[3,2,0,1] 55 | ``` 56 | 57 | 58 | 59 | 60 | 61 | 62 | **提示:** 63 | 64 | 65 | 66 | 67 | 1. `1 <= S.length <= 1000` 68 | 69 | 2. `S` 只包含字符 `"I"` 或 `"D"` 。 70 | 71 | 72 | 73 | 74 | ``` 75 | /** 76 | * @param {string} S 77 | * @return {number[]} 78 | */ 79 | var diStringMatch = function(S) { 80 | let l=0,r=S.length,res=[] 81 | let id=0 82 | while(lb-a) 87 | let max=0 88 | for(let i=0;i