其他分享
首页 > 其他分享> > 字符串 & 数学 & 其它

字符串 & 数学 & 其它

作者:互联网

剑指 Offer 38. 字符串的排列:https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof/

点击查看代码
// 思想:从剩余可选字符中填充指定位置,直到所有位置填充完成
// 注意String和char[]互转;ArrayList转数组均通过toArray(new T[0])完成
public class Solution {
    public String[] permutation(String s) {
        // 标记该元素是否已使用,剪枝
        boolean[] used = new boolean[s.length()];
        // 用于结果去重
        HashSet<String> resSet = new HashSet<>();
        dfs("", s, resSet, used);

        ArrayList<String> res = new ArrayList<>(resSet);
        return res.toArray(new String[0]);
    }

    private void dfs(String curStr, String s, HashSet<String> set, boolean[] used) {
        if (curStr.length() == s.length()) {
            set.add(curStr);
        }
        // 填充下一位置的元素
        for (int i = 0; i < s.length(); i++) {
            if (used[i]) {
                // 如果该元素已经使用了,则继续查找下一个未使用的元素
                continue;
            }
            used[i] = true;
            dfs(curStr + s.charAt(i), s, set, used);
            used[i] = false;
        }
    }
}

剑指 Offer 48. 最长不含重复字符的子字符串:https://leetcode-cn.com/problems/zui-chang-bu-han-zhong-fu-zi-fu-de-zi-zi-fu-chuan-lcof/

点击查看代码
// 最长不含重复字符的子字符串:双指针 + hashmap
public class Solution {
    public static int lengthOfLongestSubstring(String s) {
        //k-v = 字符 - 字符所在位置。如果存在重复字符,更新位置到最新
        HashMap<Character, Integer> map = new HashMap<>();
        //非重复字符串长度 = r - l, l维护的是非重复区间的左边界(l, r]
        int l = -1;
        int maxLen = 0;
        for (int r = 0; r < s.length(); r++) {
            if (map.containsKey(s.charAt(r))) {
                // 更新左指针, 取max是为了避免abba这种样例场景下l的倒退
                l = Math.max(l, map.get(s.charAt(r)));
            }
            maxLen = Math.max(maxLen, r - l);
            map.put(s.charAt(r), r);
        }
        return maxLen;
    }
}
  1. 颠倒字符串中的单词:https://leetcode-cn.com/problems/reverse-words-in-a-string/
点击查看代码
// 正则表达式实现,忽略题目O(1)的空间复杂度限制
public class Solution {
    public String reverseWords(String s) {
        // 去掉空格,个数不限 "[\\s]+", 分割的字符串数组中存在""情况
        // 去掉逗号,个数不限 "[,]+", 分割的字符串数组中存在""情况
        String[] strArr = s.split("[\\s]+");
        // 题目已保证字符串种至少存在一个单词,StringBuilder非线程安全&性能更佳
        StringBuilder builder = new StringBuilder();
        int i = strArr.length - 1;
        while (i >= 0) {
            if (strArr[i].length() > 0) {
                if (builder.length() == 0) {
                    builder.append(strArr[i]);
                } else {
                    builder.append(" ").append(strArr[i]);
                }
            }
            i--;
        }

        return builder.toString();
    }
}

// 题目限制了空间复杂度为O(1):使用subString,用r和l保存单个单词的取值区间
public class Solution {
    public String reverseWords(String s) {
        StringBuilder builder = new StringBuilder();
        int r = s.length() - 1;
        while (r >= 0) {
            // r指向单次最右边的字母
            while (r >= 0 && s.charAt(r) == ' ') {
                r--;
            }
            if (r < 0) {
                break;
            }
            // l指向单次最左边的字母
            int l = r - 1;
            while (l >= 0 && s.charAt(l) != ' ') {
                l--;
            }
            if (l < 0 && s.charAt(0) == ' ') {
                break;
            }
            l++;

            // 基于l和r截取s的子串,[l, r)
            String subStr = s.substring(l, r + 1);
            if (builder.length() == 0) {
                builder.append(subStr);
            } else {
                builder.append(" ").append(subStr);
            }

            // 更新r
            r = l - 1;
        }
        return builder.toString();
    }
}

剑指 Offer 62. 圆圈中最后剩下的数字:https://leetcode-cn.com/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof/

点击查看代码
// 通用解法:使用队列模拟实现,但m很大时模拟实现会超时
public class Solution {
    public int lastRemaining(int n, int m) {
        LinkedList<Integer> queue = new LinkedList<>();
        for (int i = 0; i < n; i++) {
            queue.add(i);
        }

        while (queue.size() > 1) {
            int i = 1;
            // 循环淘汰第m个数字
            while (i < m) {
                queue.add(queue.poll());
                i++;
            }
            queue.poll();
        }
        return queue.poll();
    }
}

// 数学推导,定义:f(n, m)表示有n个人时最后存活下来的人的编号
// 则f(n, m) = (f(n-1, m) + m) % n, 且f(1,m) = 0
public class Solution {
    public int lastRemaining(int n, int m) {
        // 最后存活下来的人的编号, n == 1
        int pos = 0;
        // 基于公式,推导初始化状态下的存活下来的人的编号n > 1
        for (int i = 2; i <= n; i++) {
            pos = (pos + m) % i;
        }
        return pos;
    }
}
  1. 用 Rand7() 实现 Rand10():https://leetcode-cn.com/problems/implement-rand10-using-rand7/
点击查看代码
// 利用rand7可产生49个随机数,基于7进制,数据取值范围是[8, 56]
// 要生成[1,10]范围随机数,每4个数对应1~10中的一个数,则需要40个数
// 因此:rand7产生的数中,我们需要的数据范围是[8,47],总共40个数
public class Solution extends SolBase {
    public int rand10() {
        // 利用rand7生成[8,47]范围中的数
        int val = 48;
        while (val > 47) {
            val = (rand7() * 7 + rand7());
        }
        // 基于val构造rand10范围的数[1,10]
        return (val - 8) / 4 + 1;
    }
}

标签:其它,String,int,builder,length,数学,字符串,new,public
来源: https://www.cnblogs.com/aizi/p/16117667.html