Leetcode刷题记录

栈:

394. 字符串解码

	[思路比较好的java实现](https://blog.csdn.net/mine_song/article/details/71036245)

——————————————————————————————————————————

树:

102.103.107、二叉树的层序遍历

三个代码差不多,改变少许细节位置即可

173. 二叉搜索树迭代器

使用栈实现

——————————————————————————————————————————

堆(优先级队列):

174. 数据流中的第K大元素

使用默认的优先级队列(小根堆)实现

175. 最接近原点的 K 个点

自定义比较器的堆

176. 根据字符出现频率排序 347.均是进行词频排序:

/* 1、统计词频,存入hashmap中; 2、自定义比较器存入堆中; */
自定义比较器的堆实现词频统计

——————————————————————————————————————————

排序:

148排序链表

https://leetcode-cn.com/problems/sort-list/submissions/
归并排序:快慢指针找寻中间节点和外排merge

147. 对链表进行插入排序

https://leetcode-cn.com/problems/insertion-sort-list/submissions/

56 合并区间

https://leetcode-cn.com/problems/merge-intervals/submissions/
贪心算法

524.通过删除字母匹配到字典里最长单词

本人解法:https://leetcode-cn.com/problems/longest-word-in-dictionary-through-deleting/
1、获取满足条件的子串;
2、自定义排序

75.颜色分类

本人解法(两种)https://leetcode-cn.com/problems/sort-colors/
方案1、给定元素范围,可以使用桶排序;
方案2、三类,可直接使用快排的partition过程

274.H指数

本人解法:https://leetcode-cn.com/problems/h-index/
1、排序
2、画图找规律

767.重构字符串

给定一个字符串S,检查是否能重新排布其中的字母,使得两相邻的字符不同。
若可行,输出任意可行的结果。若不可行,返回空字符串。

示例 1:
输入: S = "aab"
输出: "aba"
示例 2:
输入: S = "aaab"
输出: ""

本人解法:https://leetcode-cn.com/submissions/detail/16485263/
1、map统计词频;
2、大根堆存放;
3、贪心append字符串:每次取出堆顶最大的两个,更新count

179.最大数

给定一组非负整数,重新排列它们的顺序使之组成一个最大的整数。

示例 1:
输入: [10,2]
输出: 210
示例 2:
输入: [3,30,34,5,9]
输出: 9534330

1、使用a+b与b+a的大小进行比较排序;
2、连接字符串,注意0值的处理;
本人解法(用大根堆实现):https://leetcode-cn.com/problems/largest-number/submissions/
更优解法(直接arrays自定义排序):http://www.cnblogs.com/271934Liao/p/7101642.html

324. 摆动排序 II

给定一个无序的数组 nums,将它重新排列成 nums[0] < nums[1] > nums[2] < nums[3]… 的顺序。

示例 1:

输入: nums = [1, 5, 1, 1, 6, 4]
输出: 一个可能的答案是 [1, 4, 1, 5, 1, 6]
示例 2:

输入: nums = [1, 3, 2, 2, 3, 1]
输出: 一个可能的答案是 [2, 3, 1, 3, 1, 2]

1、Arrays.sort进行排序,分为大数和小数两部分,以(arr.length+1)/2为边界;
2、大数和小数插空填充;
本人代码,比较繁琐:https://leetcode-cn.com/problems/wiggle-sort-ii/submissions/
更简单的解答:

class Solution {
    //首先创建一个temp数组保存排序过后的数组
    //然后求出temp数组的left 和right部分,分别从left 和right的末端开始取值填充到原数组中
    public void wiggleSort(int[] nums) {
            if (nums == null || nums.length == 1) return;
            int[] temp = Arrays.copyOf(nums, nums.length);
            Arrays.sort(temp);
            int m = (temp.length - 1) / 2, n = temp.length - 1;
            for (int i = 0; i < nums.length; i++) {
                nums[i] = (i % 2) == 0 ? temp[m--] : temp[n--];
            }
    }

————————————————————————————————————————————

位运算

461. 汉明距离
两个整数之间的汉明距离指的是这两个数字对应二进制位不同的位置的数目。
给出两个整数 x 和 y,计算它们之间的汉明距离。
注意:
0 ≤ x, y < 231.

示例:
输入: x = 1, y = 4
输出: 2
解释:
1   (0 0 0 1)
4   (0 1 0 0)
       ↑   ↑
上面的箭头指出了对应二进制位不同的位置。

本人解法:https://leetcode-cn.com/submissions/detail/16558834/
1、两个数异或,则汉明距离就是1的个数;
2、计算1的个数见剑指offer15:x=(x-1)&x;

476. 数字的补数
给定一个正整数,输出它的补数。补数是对该数的二进制表示取反。
注意:
给定的整数保证在32位带符号整数的范围内。
你可以假定二进制数不包含前导零位。

示例 1:
输入: 5
输出: 2
解释: 5的二进制表示为101(没有前导零位),其补数为010。所以你需要输出2。

示例 2:
输入: 1
输出: 0
解释: 1的二进制表示为1(没有前导零位),其补数为0。所以你需要输出0。

本人解法:https://leetcode-cn.com/problems/number-complement/submissions/
1、找到num数中最高位的位置,即101到100;
2、100->1000->111;
3、步骤2中获得的结果与原数进行异或

136. 只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例 1:
输入: [2,2,1]
输出: 1

示例 2:
输入: [4,1,2,1,2]
输出: 4

本人解法:https://leetcode-cn.com/problems/single-number/
两个相同的数异或的结果为0;
所以所有的数异或所得就是所求;

762. 二进制表示中质数个计算置位
给定两个整数 L 和 R ,找到闭区间 [L, R] 范围内,计算置位位数为质数的整数个数。
(注意,计算置位代表二进制表示中1的个数。例如 21 的二进制表示 10101 有 3 个计算置位。还有,1 不是质数。)

示例 1:
输入: L = 6, R = 10
输出: 4
解释:
6 -> 110 (2 个计算置位,2 是质数)
7 -> 111 (3 个计算置位,3 是质数)
9 -> 1001 (2 个计算置位,2 是质数)
10-> 1010 (2 个计算置位,2 是质数)

示例 2:
输入: L = 10, R = 15
输出: 5
解释:
10 -> 1010 (2 个计算置位, 2 是质数)
11 -> 1011 (3 个计算置位, 3 是质数)
12 -> 1100 (2 个计算置位, 2 是质数)
13 -> 1101 (3 个计算置位, 3 是质数)
14 -> 1110 (3 个计算置位, 3 是质数)
15 -> 1111 (4 个计算置位, 4 不是质数)
注意:
L, R 是 L <= R 且在 [1, 10^6] 中的整数。
R - L 的最大值为 10000。

本人解法:https://leetcode-cn.com/problems/prime-number-of-set-bits-in-binary-representation/
1、循环计算每一个数;
2、计算每个数的1的个数(x &= (x - 1));
3、判断是否为质数;(不知道10^6范围,最多写出32位即可);
4、统计。

169. 求众数
给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在众数。

示例 1:
输入: [3,2,3]
输出: 3

示例 2:
输入: [2,2,1,1,1,2,2]
输出: 2

解法:https://leetcode-cn.com/problems/majority-element/submissions/
摩尔投票算法:https://blog.csdn.net/u014248127/article/details/79230221

public int majorityElement(int[] nums) {
        int res = 0 , count = 0;
        for(int num : nums){
            if(num == res){
                count++;
            }else if(count == 0){
                res = num;
                count++;
            }else{
                count--;
            }
        }
        return res;
    }

229. 求众数 II
给定一个大小为 n 的数组,找出其中所有出现超过 ⌊ n/3 ⌋ 次的元素。
说明: 要求算法的时间复杂度为 O(n),空间复杂度为 O(1)。

示例 1:

输入: [3,2,3]
输出: [3]
示例 2:

输入: [1,1,1,3,3,2,2,2]
输出: [1,2]

解答:https://leetcode-cn.com/problems/majority-element-ii/
摩尔投票算法的进阶形式,甚至可以推广到n分之一:

//摩尔投票算法的进阶形式,维护两个计数器和初始数
    public List majorityElement(int[] nums) {
        int res1 = 0 , res2 = 0;
        int count1 = 0 , count2 = 0;
        //算出可能的两个解
        for(int num : nums){
            if(num == res1){
                count1++;
            }else if(num == res2){
                count2++;
            }else if(count1 == 0){
                count1++;
                res1 = num;
            }else if(count2 == 0){
                count2++;
                res2 = num;
            }else{
                count1--;
                count2--;
            }
        }
        //判断两个res1和res2是否都满足条件
        List list = new ArrayList<>();
        count1 = 0;
        count2 = 0;
        for(int num : nums){
            if(res1 == num)
                count1++;
            else if(res2 == num)
                count2++;
        }
        if(count1 > nums.length/3)
            list.add(res1);
        if(count2 > nums.length/3)
            list.add(res2);
        return list;
    }

389. 找不同
给定两个字符串 s 和 t,它们只包含小写字母。
字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母。
请找出在 t 中被添加的字母。

示例:
输入:
s = "abcd"
t = "abcde"
输出:
e
解释:
'e' 是那个被添加的字母。

解答:https://leetcode-cn.com/problems/find-the-difference/submissions/
解法一:使用桶来实现;
解法二:2n+1个数找出唯一的那一个,所有数异或。

371. 两整数之和
不使用运算符 + 和 - ​​​​​​​,计算两整数 ​​​​​​​a 、b ​​​​​​​之和。

示例 1:
输入: a = 1, b = 2
输出: 3

示例 2:
输入: a = -2, b = 3
输出: 1

解法如下:见剑指offer65

class Solution {
    //不能用+、-,只能用位运算来代替+,-
    //1、不考虑进位对每一位进行相加:1001+101 = 1100;很明显使用异或^;
    //2、计算进位:1001+0101 = 10:很明显是与&运算之后左移一位<<;
    //3、将1的结果与2的进位相加,重复运算,直到进位为0;
    public int getSum(int a, int b) {
        int sum = 0;
        int carry = 0;//表示进位
        while(b != 0){
            sum = a ^ b ;
            carry = ( a & b )<<1;
            a = sum ; 
            b = carry ;
        }
        return sum;
    }
}

268. 缺失数字
给定一个包含 0, 1, 2, …, n 中 n 个数的序列,找出 0 … n 中没有出现在序列中的那个数。

示例 1:
输入: [3,0,1]
输出: 2

示例 2:
输入: [9,6,4,2,3,5,7,0,1]
输出: 8

两种解法:https://leetcode-cn.com/problems/missing-number/
1、求和;
2、使用位运算:假设0~n数字没有缺失的话,对0~n进行异或,可以得到一个确定的数字,然后对缺失数字的数组进行异或,可以得到另一个数字,这两个数字的异或,就是缺失的数字。

342. 4的幂
给定一个整数 (32 位有符号整数),请编写一个函数来判断它是否是 4 的幂次方。

示例 1:
输入: 16
输出: true

示例 2:
输入: 5
输出: false

两种解法(普通移位运算和数字特征观察):https://leetcode-cn.com/problems/power-of-four/

405. 数字转换为十六进制数
给定一个整数,编写一个算法将这个数转换为十六进制数。对于负整数,我们通常使用 补码运算 方法。
注意:
十六进制中所有字母(a-f)都必须是小写。
十六进制字符串中不能包含多余的前导零。如果要转化的数为0,那么以单个字符’0’来表示;对于其他情况,十六进制字符串中的第一个字符将不会是0字符。
给定的数确保在32位有符号整数范围内。
不能使用任何由库提供的将数字直接转换或格式化为十六进制的方法。

示例 1:
输入:
26
输出:
"1a"

示例 2:
输入:
-1
输出:
"ffffffff"

解法如下:

class Solution {
    public String toHex(int num) {
        if(num == 0)
            return "0";
        StringBuilder s = new StringBuilder("");
        char[] dic = new char[]{'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
        //<8是针对负数的,因为负数32位都有值,!=0针对正数
        while(s.length() < 8 && num != 0){
        	//负数不能用%16,所以要用位运算
            System.out.println((num&0xf)+","+dic[num&0xf]);
            s.append(dic[num&0xf]);
            num = num>>4;
        }
        return s.reverse().toString();
    }
}

——————————————————————————————————————————

树:

108. 将有序数组转换为二叉搜索树

将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。
本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。

示例:
给定有序数组: [-10,-3,0,5,9],
一个可能的答案是:[0,-3,9,-10,null,5],它可以表示下面这个高度平衡二叉搜索树:
      0
     / \
   -3   9
   /   /
 -10  5

二叉树重建的典型案例,解法如下:https://leetcode-cn.com/problems/convert-sorted-array-to-binary-search-tree/
没什么新鲜的东西了。这种区间分治类的题目,用左闭右闭就好,左闭右开不方便。
另外需要注意的是,求中点不要用 int mid = (l + r)/2,有溢出风险,稳妥的方法是 int mid = l + (r-l)/2; 如果你把除2改成右移1位,会和面试官更搭哦。

你可能感兴趣的:(leetcode刷题)