字符串 & 数学 & 其它
作者:互联网
剑指 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;
}
}
点击查看代码
// 正则表达式实现,忽略题目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;
}
}
- 用 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