基础算法案例

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

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

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

解法一:位运算

class Solution {
    public int singleNumber(int[] nums) {
        int result=0;
        for(int num:nums){
            result^=num;
        }
        return result;
    }
}

解法二:哈希表

/*Map的基本操作——put、get、containsKey、containsValue、size以及isEmpty*/
    //使用map
    public int findOnly(int [] nums){
        Map<Integer,Integer> map=new HashMap<>();
        for(Integer i:nums){
            map.put(i,map.containsKey(i)? map.get(i)+1:1);
        }
        for (Map.Entry<Integer, Integer> en: map.entrySet()) {
            int key = en.getKey();
            int value = en.getValue();
            if (value==1) return key;
        }
        return -1;
    }

(2)多数元素
给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

示例 1:

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

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

public int majorityElement(int[] nums) {
         Map<Integer,Integer> map=new HashMap<>();
        for(int i:nums){
            map.put(i,map.containsKey(i)?map.get(i)+1:1);
        }
        int resultkey=-1;
        int resultvalue=0;
        for(Map.Entry<Integer,Integer> en:map.entrySet()){
            int key=en.getKey();
            int value=en.getValue();
            if(value>resultvalue){
                resultkey=key;
                resultvalue=value;
            }
        }
        return resultkey;
    }

(3)统计「优美子数组」

题目描述
给你一个整数数组 nums 和一个整数 k。

如果某个连续子数组中恰好有 k 个奇数数字,我们就认为这个子数组是「优美子数组」。

请返回这个数组中「优美子数组」的数目。

示例 1:


输入:nums = [1,1,2,1,1], k = 3
输出:2
解释:包含 3 个奇数的子数组是 [1,1,2,1] 和 [1,2,1,1] 。
示例 2:


输入:nums = [2,4,6], k = 1
输出:0
解释:数列中不包含任何奇数,所以不存在优美子数组。
示例 3:


输入:nums = [2,2,2,1,2,2,1,2,2,2], k = 2
输出:16
数据范围
 @Test
    public void test2(){
        int []nums={2,2,2,1,2,2,1,2,2,2};
        int k=2;
        int result=firstarray(nums,k);
        System.out.println(result);

    }
    public int firstarray(int []nums,int k){
        int result=0;
        for(int i=0;i<nums.length-k;i++){
            int count=0;
            for(int j=i;count<=k && j<nums.length;j++){
                if(nums[j]%2==1) count++;
                if(count==k){
                    result++;
                }
            }
        }
        return result;
    }
面试题 01.01. 判定字符是否唯一
    * 实现一个算法,确定一个字符串 s 的所有字符是否全都不同。

示例 1:

输入: s = "leetcode"
输出: false
示例 2:

输入: s = "abc"
输出: true


#Map解法
public boolean isUnique(String astr) {
         char [] chars=astr.toCharArray();
        Map<Character,Integer> map=new HashMap<>();
        for(char ch: chars){
            map.put(ch,map.containsKey(ch)?map.get(ch)+1:1);
            if (map.get(ch)>=2) return false;
        }
        return true;
    }

#Set解法
#利用 Set 不可重复性
 public boolean isUnique(String astr) {
        Set<Character> set = new HashSet<>();
        for (int i = 0; i < astr.length(); i++) {
            set.add(astr.charAt(i));
        }
        return set.size() == astr.length();
    }

面试题 01.02. 判定是否互为字符重排
给定两个字符串 s1 和 s2,请编写一个程序,确定其中一个字符串的字符重新排列后,能否变成另一个字符串。

示例 1:

输入: s1 = "abc", s2 = "bca"
输出: true
示例 2:

输入: s1 = "abc", s2 = "bad"
输出: false
 /*此方法遇到s1=aab,s2=abb时解答错误*/
    public boolean CheckPermutation(String s1, String s2) {
        char []chars=s1.toCharArray();
        if(s1.length()!=s2.length()) return false;
        for(char ch:chars){
            if(s2.indexOf(ch)==-1) return false;
        }
        return true;
    }
//正确解法
    public boolean CheckPermutation2(String s1, String s2) {
        if(s1.length()!=s2.length()) return false;
        char []chars1=s1.toCharArray();
        Arrays.sort(chars1);
        char []chars2=s2.toCharArray();
        Arrays.sort(chars2);
        for(int i=0;i<chars1.length;i++){
            if(chars1[i]!=chars2[i]) return false;
        }
        return true;
    }

最长回文子串
给你一个字符串 s,找到 s 中最长的回文子串。

示例 1:

输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
示例 2:

输入:s = "cbbd"
输出:"bb"

   /*暴力求解
暴力求解是最容易想到的,要截取字符串的所有子串,然后再判断这些子串中哪些是回文的,最后返回回文子串中最长的即可。
这里我们可以使用两个变量,一个记录最长回文子串开始的位置,一个记录最长回文子串的长度,最后再截取。代码如下*/
@Test
    public void testlongestPalindrome(){
        String s="babad";
        String result=longestPalindrome(s);
        System.out.println(result);
    }
    public String longestPalindrome(String s) {
        if(s.length()<2) return s;
        int start=0;
        int maxLen=0;
        for(int i=0;i<s.length()-1;i++){
            for(int j=i;j<s.length();j++){
                if(maxLen>j-i+1) continue;;
                if(Palindrome(s,i,j)){
                    if(maxLen<j-i+1){
                        start=i;
                        maxLen=j-i+1;
                    }
                }
            }
        }
        return s.substring(start,start+maxLen);

    }
    public boolean Palindrome(String s,int start,int end){
        while (start<end){
            if(s.charAt(start)!=s.charAt(end)) return false;
            start++;
            end--;
        }
        return true;
    }

穿插一个小知识点:解决斐波那契数列中递归的重复计算

/* 递归改进:那么避免重复计算的方法就是,每计算得到一个值,便用一个数组保存这个值,下次计算该值的时候直接引用就可以了。*/
public int fibonacci(int n) {
    int[] array = new int[n + 1];

    if (n < 2) {return 0;}
    if (2 == n) {return 1;}
    array[1] = 0;
    array[2] = 1;

    return helper(array, n);
}

private int helper(int[] array, int n) {
    if (n < 2) {
        return 0;
    }
    if (2 == n) {
        return 1;
    }
    array[n] = helper(array, n - 1) + array[n - 2]; // 保存每次计算的结果
    return array[n];
}

动态规划算法题:

 /*爬楼梯
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
示例 1:

输入:n = 2
输出:2
解释:有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶
示例 2:

输入:n = 3
输出:3
解释:有三种方法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1 阶
2. 1 阶 + 2 阶
3. 2 阶 + 1 阶
*/
    @Test
    public void testclimbStairs(){

        int result=climbStairs(5);
        System.out.println(result);
    }
    public int climbStairs(int n) {
        if(n==1) return 1;
        if(n==2) return  2;
        int []num=new int[n+1];
        num[1]=1;
        num[2]=2;
        for(int i=3;i<=n;i++){
            num[i]=num[i-1]+num[i-2];
        }
        return num[n];
    }


    /*最大子数组和:给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组 是数组中的一个连续部分。
示例 1:
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
示例 2:

输入:nums = [1]
输出:1
示例 3:

输入:nums = [5,4,-1,7,8]
输出:23
*/
    @Test
    public void testmaxSubArray(){
        int []nums = {-2,1,-3,4,-1,2,1,-5,4};
        int result=maxSubArray(nums);
        System.out.println(result);
    }
    public int maxSubArray(int[] nums) {
        int len=nums.length;
        //dip[i]表示:以num[i]结尾的连续子数组的最大和
        int [] dp=new int[len];
        for(int i=1;i<len;i++){
            if(dp[i-1]>0){
                dp[i]=dp[i-1]+nums[i];
            }else {
                dp[i]=nums[i];
            }
        }
        //求最大值
        int res=dp[0];
        for(int i=1;i<len;i++){
            res=Math.max(res,dp[i]);
        }
        return res;
    }
    /*最长回文子串
给你一个字符串 s,找到 s 中最长的回文子串。

示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
示例 2:

输入:s = "cbbd"
输出:"bb"
*/

    public String longestPalindrome(String s) {
        if (s.length() < 2)
            return s;
        int start = 0;
        int maxLen = 0;
        for (int i = 0; i < s.length() - 1; i++) {
            for (int j = i; j < s.length(); j++) {
                //截取所有子串,如果截取的子串小于等于之前
                //遍历过的最大回文串,直接跳过。因为截取
                //的子串即使是回文串也不可能是最大的,所以
                //不需要判断
                if (j - i < maxLen)
                    continue;
                if (isPalindrome(s, i, j)) {
                    if (maxLen < j - i + 1) {
                        start = i;
                        maxLen = j - i + 1;
                    }
                }
            }
        }
        return s.substring(start, start + maxLen);
    }

    //判断是否是回文串
    private boolean isPalindrome(String s, int start, int end) {
        while (start < end) {
            if (s.charAt(start++) != s.charAt(end--))
                return false;
        }
        return true;
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值