Leetcode面T17(1-10)树

Q17.1 树不用加号的加法

设计一个函数把两个数字相加。不得使用 + 或者其他算术运算符。

示例:

输入: a = 1, b = 1
输出: 2
 

提示:

a, b 均可能是负数或 0
结果不会溢出 32 位整数

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/add-without-plus-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution {
    public static int add(int a, int b) {
        int sum = 0, carry = 0;
        while(b != 0) {
        	sum = a ^ b;			// 异或计算未进位的部分
        	carry = (a & b) << 1;	// 进位部分
        	a = sum;				// 保存未进位部分,再次计算
        	b = carry;				// 保存进位部分,再次计算
        }
        return a;	// 最后无进位,异或的结果即加法结果
    }
}

Q17.4 消失的数字

数组nums包含从0到n的所有整数,但其中缺了一个。请编写代码找出那个缺失的整数。你有办法在O(n)时间内完成吗?

注意:本题相对书上原题稍作改动

示例 1:

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

示例 2:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/missing-number-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

先求0-n和,最后减去sum(nums)

class Solution {
    public int missingNumber(int[] nums) {
        int sum = 0;
	for (int i = 0; i < nums.length; i++) sum += nums[i];
	return nums.length * (nums.length + 1) / 2 - sum;
   }
}

Q17.5 字母与数字

给定一个放有字符和数字的数组,找到最长的子数组,且包含的字符和数字的个数相同。

返回该子数组,若存在多个最长子数组,返回左端点最小的。若不存在这样的数组,返回一个空数组。

示例 1:

输入: ["A","1","B","C","D","2","3","4","E","5","F","G","6","7","H","I","J","K","L","M"]

输出: ["A","1","B","C","D","2","3","4","E","5","F","G","6","7"]
示例 2:

输入: ["A","A"]

输出: []
提示:

array.length <= 100000

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-longest-subarray-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

public String[] findLongestSubarray(String[] array) {
        int start = 0;
        int end = 0;
        HashMap<Integer, Integer> leftIndexMap = new HashMap<>();
        int preSum = 0;
        leftIndexMap.put(0, -1);
        for (int i = 0; i < array.length; i++) {
            preSum += Character.isDigit(array[i].charAt(0)) ? 1 : -1;
            if (!leftIndexMap.containsKey(preSum)) {
                leftIndexMap.put(preSum, i);
            } else {
                int leftIndex = leftIndexMap.get(preSum);
                if (i - leftIndex > end - start) {
                    start = leftIndex;
                    end = i;
                }
            }
        }
        return Arrays.copyOfRange(array, start + 1, end + 1);
    }

Q17.6 2出现的次数

编写一个方法,计算从 0 到 n (含 n) 中数字 2 出现的次数。

示例:

输入: 25
输出: 9
解释: (2, 12, 20, 21, 22, 23, 24, 25)(注意 22 应该算作两次)
提示:

n <= 10^9

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/number-of-2s-in-range-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution {
    public int numberOf2sInRange(int n) {
        int ans=0;
        for(long i=1;i<=n;i*=10){
            int temp=(int) (n/i);
            int cur=temp%10;
            int temp1=temp/10;
            int temp2=(int) (n%i);
            ans+=(int) (temp1*i);
            if(cur==2) ans+=temp2+1;
            if(cur>2) ans+=i;
        }
        return ans;
    }
}

 

Q17.7 婴儿名字

每年,政府都会公布一万个最常见的婴儿名字和它们出现的频率,也就是同名婴儿的数量。有些名字有多种拼法,例如,John 和 Jon 本质上是相同的名字,但被当成了两个名字公布出来。给定两个列表,一个是名字及对应的频率,另一个是本质相同的名字对。设计一个算法打印出每个真实名字的实际频率。注意,如果 John 和 Jon 是相同的,并且 Jon 和 Johnny 相同,则 John 与 Johnny 也相同,即它们有传递和对称性。

在结果列表中,选择字典序最小的名字作为真实名字。

示例:

输入:names = ["John(15)","Jon(12)","Chris(13)","Kris(4)","Christopher(19)"], synonyms = ["(Jon,John)","(John,Johnny)","(Chris,Kris)","(Chris,Christopher)"]
输出:["John(27)","Chris(36)"]
提示:

names.length <= 100000

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/baby-names-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution {
    public String[] trulyMostPopular(String[] names, String[] synonyms) {
        Map<String, Integer> map = new HashMap<>();
        Map<String, String> unionMap = new HashMap<>();
        for (String name : names) {     //统计频率
            int idx1 = name.indexOf('(');
            int idx2 = name.indexOf(')');
            int frequency = Integer.valueOf(name.substring(idx1 + 1, idx2));
            map.put(name.substring(0, idx1), frequency);
        }
        for (String pair : synonyms) {  //union同义词
            int idx = pair.indexOf(',');
            String name1 = pair.substring(1, idx);
            String name2 = pair.substring(idx + 1, pair.length() - 1);
            while (unionMap.containsKey(name1)) {   //找name1祖宗
                name1 = unionMap.get(name1);
            }
            while (unionMap.containsKey(name2)) {   //找name2祖宗
                name2 = unionMap.get(name2);
            }
            if(!name1.equals(name2)){   //祖宗不同,要合并
                int frequency = map.getOrDefault(name1, 0) + map.getOrDefault(name2, 0);    //出现次数是两者之和
                String trulyName = name1.compareTo(name2) < 0 ? name1 : name2;
                String nickName = name1.compareTo(name2) < 0 ? name2 : name1;
                unionMap.put(nickName, trulyName);      //小名作为大名的分支,即大名是小名的祖宗
                map.remove(nickName);       //更新一下数据
                map.put(trulyName, frequency);
            }
        }
        String[] res = new String[map.size()];
        int index = 0;
        for (String name : map.keySet()) {
            StringBuilder sb = new StringBuilder(name);
            sb.append('(');
            sb.append(map.get(name));
            sb.append(')');
            res[index++] = sb.toString();
        }
        return res;
    }
}

Q17.8 马戏团人塔

有个马戏团正在设计叠罗汉的表演节目,一个人要站在另一人的肩膀上。出于实际和美观的考虑,在上面的人要比下面的人矮一点且轻一点。已知马戏团每个人的身高和体重,请编写代码计算叠罗汉最多能叠几个人。

示例:

输入:height = [65,70,56,75,60,68] weight = [100,150,90,190,95,110]
输出:6
解释:从上往下数,叠罗汉最多能叠 6 层:(56,90), (60,95), (65,100), (68,110), (70,150), (75,190)
提示:

height.length == weight.length <= 10000

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/circus-tower-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution {
    public int bestSeqAtIndex(int[] height, int[] weight) {
        int len = height.length;
        int[][] person = new int[len][2];
        for (int i = 0; i < len; ++i)
            person[i] = new int[]{height[i], weight[i]};

        Arrays.sort(person, (a, b) -> a[0] == b[0] ? b[1] - a[1] : a[0] - b[0]);
        int[] dp = new int[len];
        int res = 0;
        for (int[] pair : person) {
            int i = Arrays.binarySearch(dp, 0, res, pair[1]);
            if (i < 0)
                i = -(i + 1);
            dp[i] = pair[1];
            if (i == res)
                ++res;
        }
        return res;
    }
}

Q17.9 第 k 个数

有些数的素因子只有 3,5,7,请设计一个算法找出第 k 个数。注意,不是必须有这些素因子,而是必须不包含其他的素因子。例如,前几个数按顺序应该是 1,3,5,7,9,15,21。

示例 1:

输入: k = 5

输出: 9

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/get-kth-magic-number-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution {
   /**
     * 题目分析:
     *  由题意的,某一个满足结果的数,一定是之前的某个 resultA*3 或者是 resultB*5 或者是 resultC*7 的结果
     *  并且结果一定是 这三个乘积的最小值,
     *  因此,只要能够记录 resultA、resultB、resultC 的值,再相互与 3、5、7 相乘,取其中的最小值,就是当前的目标值!
     *  需要注意,resultA、B、C 是不断变化的,并且都应该是由小到大,谁被选中,就应该取下一个值!
     *      例如 3 就是 resultA=1 的结果,此时 B、C 都等于 1,此后 resultA 取下一个值 3 
     *      例如 5 就是 resultB=1 的结果,此时 resultA=3,resultC=1,此后 resultB 取下一个值 3
     *      例如 7 就是 resultC=1 的结果,此时 resultA、resultB 都等于 3,此后 resultC 取下一个值 3
     *      例如 15 就是 resultA=5 或者是 resultB=3 的结果,此时 resultC=7,此后 resultA 取下一个值 7 ,resultB 取下一个值 5
     *      自己在纸上多画画,就明白了!
     * @param k
     * @return
     */
    public int getKthMagicNumber(int k) {
        int [] result = new int[k];
        result[0] = 1;
        // 定义三个 指针,分别表示 resultA、B、C 的下标
        int point3 = 0;
        int point5 = 0;
        int point7 = 0;
        for (int i = 1; i < k; i++) {
            int resultN = Math.min(Math.min(result[point3] * 3, result[point5] * 5), result[point7] * 7);
            if (resultN % 3 == 0) {
                point3++;
            }
            if (resultN % 5 == 0) {
                point5++;
            }
            if (resultN % 7 == 0) {
                point7++;
            }
            result[i] = resultN;
        }
        return result[k - 1];
    }
}

Q17.10 主要元素

数组中占比超过一半的元素称之为主要元素。给定一个整数数组,找到它的主要元素。若没有,返回-1。

示例 1:

输入:[1,2,5,9,5,9,5,5,5]
输出:5
 

示例 2:

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

示例 3:

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

说明:
你有办法在时间复杂度为 O(N),空间复杂度为 O(1) 内完成吗?

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-majority-element-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

//投票算法
class Solution {
    public int majorityElement(int[] nums) {
        int taotal = 1;
        int people= nums[0];
        for(int i = 1;i<nums.length;i++){
            if(people!=nums[i]){
                taotal--;
            }else{
                taotal++;
            }
            if(taotal<0){
                people = nums[i];
                taotal = 1; 
            }
        }
        return taotal>0?people:-1;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值