java常见算法

1.广度优先搜索

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {

        List<List<Integer>> res = new ArrayList<>();

        if(root == null)
        return res;

        Queue<TreeNode> q = new LinkedList<>();
        q.offer(root);

        while(!q.isEmpty()) {

            List<Integer> tr = new ArrayList<>();

            int n = q.size();

            for(int i = 0;i < n;i++) {

                TreeNode r = q.poll();
                tr.add(r.val);
                if(r.left != null) {
                    q.offer(r.left);
                }

                if(r.right != null) {
                    q.offer(r.right);
                }

            }
            res.add(tr);
        }

        return res;
    }
}

2.链表知识

1.进制:709 + 201 的反转链表为 907 + 102,得出一个一模一样反转和 例如9 + 1 >= 10,则该位置取加起来数字的个位数,后面的值交给下一位来相加

题目:

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {

        ListNode res = null,temp = null;
        int c = 0;

        while(l1 != null || l2 != null) {

            int a = l1 != null ? l1.val : 0;
            int b = l2 != null ? l2.val : 0;
            int sum = a + b + c;

            if(res == null) {

                res = temp = new ListNode(sum % 10);
            }else {

                temp.next = new ListNode(sum % 10);
                temp = temp.next;
            }

            c = sum / 10;
            if(l1 != null) {

                l1 = l1.next;
            }

            if(l2 != null) {

                l2 = l2.next;
            }
        }

        if(c > 0) {

            temp.next = new ListNode(c);
        }

        return res;

    }
}

3.

题目:

给定一个经过编码的字符串,返回它解码后的字符串。

编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。

你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。

此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。

示例 1:

输入:s = "3[a]2[bc]"
输出:"aaabcbc"
示例 2:

输入:s = "3[a2[c]]"
输出:"accaccacc"
示例 3:

输入:s = "2[abc]3[cd]ef"
输出:"abcabccdcdcdef"
示例 4:

输入:s = "abc3[cd]xyz"
输出:"abccdcdcdxyz"

1.栈解决

class Solution {
    public String decodeString(String s) {

        StringBuilder res = new StringBuilder();
        int multi = 0;

        //用于存放倍数
        LinkedList<Integer> sta_mul = new LinkedList<>();

        //用于存放一段字符串
        LinkedList<String> sta_res = new LinkedList<>();

        for(Character c : s.toCharArray()) {

            if(c == '[') {

                sta_mul.addLast(multi);
                sta_res.addLast(res.toString());
                multi = 0;
                res = new StringBuilder();
            }else if(c == ']') {

                StringBuilder tmp = new StringBuilder();
                int now_mul = sta_mul.removeLast();
                for(int i = 0;i < now_mul;i++) {

                    tmp.append(res);
                }

                res = new StringBuilder(sta_res.removeLast() + tmp);
            }else if(c >= '0' && c <= '9') {

                multi = multi * 10 + Integer.parseInt(c + "");

            }else {
                res.append(c);
            }
        }
        return res.toString();
    }
}

2.递归

class Solution {
    public String decodeString(String s) {

        return dfs(0,s)[0];
    }

    public String[] dfs(int i,String s) {

        StringBuilder res = new StringBuilder();
        int mul = 0;

        while(i < s.length()) {

            if(s.charAt(i) >= '0' && s.charAt(i) <= '9') {

                mul = mul * 10 + Integer.parseInt(String.valueOf(s.charAt(i)));
            }else if(s.charAt(i) == '[') {

                //递归获取[]之间的字符串
                String[] arr = dfs(i + 1,s);
                i = Integer.parseInt(arr[0]);
                String re = arr[1];
                
                //也将mul--为0以便下次操作
                while(mul > 0) {

                    res.append(re);
                    mul--;
                }
            }else if(s.charAt(i) == ']') {

                return new String[]{String.valueOf(i),res.toString()};
            }else {

                res.append(String.valueOf(s.charAt(i)));
            }
            i++;
        }

        return new String[]{res.toString()};
    }
}

4.动态规划

给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s 。

注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。

示例 1:

输入: s = "leetcode", wordDict = ["leet", "code"]
输出: true
解释: 返回 true 因为 "leetcode" 可以由 "leet" 和 "code" 拼接成。
示例 2:

输入: s = "applepenapple", wordDict = ["apple", "pen"]
输出: true
解释: 返回 true 因为 "applepenapple" 可以由 "apple" "pen" "apple" 拼接成。
     注意,你可以重复使用字典中的单词。
示例 3:

输入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
输出: false

class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {

        int length = s.length();
        Set<String> set = new HashSet(wordDict);
        boolean[] dp = new boolean[length + 1];
        dp[0] = true;

        //i从1开始不仅为了substring还为了dp数组
        for(int i = 1;i <= length;i++) {

            for(int j = 0;j < i;j++) {

                if(dp[j] && wordDict.contains(s.substring(j,i))) {

                    //i前面的都符合
                    dp[i] = true;
                    break;
                }
            }
        }

        return dp[length];
    }
}

5.二分法

给你一个 下标从 0 开始 的整数数组 candies 。数组中的每个元素表示大小为 candies[i] 的一堆糖果。你可以将每堆糖果分成任意数量的 子堆 ,但 无法 再将两堆合并到一起。

另给你一个整数 k 。你需要将这些糖果分配给 k 个小孩,使每个小孩分到 相同 数量的糖果。每个小孩可以拿走 至多一堆 糖果,有些糖果可能会不被分配。

返回每个小孩可以拿走的 最大糖果数目 。

示例 1:

输入:candies = [5,8,6], k = 3
输出:5
解释:可以将 candies[1] 分成大小分别为 5 和 3 的两堆,然后把 candies[2] 分成大小分别为 5 和 1 的两堆。现在就有五堆大小分别为 5、5、3、5 和 1 的糖果。可以把 3 堆大小为 5 的糖果分给 3 个小孩。可以证明无法让每个小孩得到超过 5 颗糖果。
示例 2:

输入:candies = [2,5], k = 11
输出:0
解释:总共有 11 个小孩,但只有 7 颗糖果,但如果要分配糖果的话,必须保证每个小孩至少能得到 1 颗糖果。因此,最后每个小孩都没有得到糖果,答案是 0 。

class Solution {
    public int maximumCandies(int[] candies, long k) {

        int len = candies.length;
        long sum = 0;

        for(int i = 0;i < len;i++) {

            sum += candies[i];
        }

        if(sum < k)
        return 0;
        int res = 0;
        Arrays.sort(candies);

        int left = 1;
        int right = (int) (sum / k);

        while(left <= right) {

            long now = 0;
            int mid = left + (right - left) / 2;
            for(int i = len-1;i >=0;i--) {

                if(candies[i] < mid) 
                break;
                now += candies[i] / mid;
            }

            if(now >= k) {
                left = mid + 1;
                res = mid;
            }else {
                right = mid - 1;
            }
        }

        return res;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海边的彩虹与你

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值