public String reverseLeftWords(String s, int n) {
return s.substring(n)+s.substring(0,n);
}
public String reverseWords(String s) {
s = s.trim();
char[] arr = s.toCharArray();
for (int i = 1; i < arr.length; i++) {
if (arr[i] == ' ' && arr[i - 1] == ' ')
arr[i - 1] = '|';
}
String s1 = "", res ="";
for(char c:arr)
s1 += c+"";
String[] split = s1.replace("|","").split(" ");
for(int i=split.length-1; i>=0; i--)
res += split[i] + " ";
return res.trim();
}
输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。
序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
public int[][] findContinuousSequence(int target) {
ArrayList<int[]> list = new ArrayList<>();
int i=1,j=2, sum=1+2;
while(i<=target/2 && j<=target/2+1){
if(sum>target){
sum -= i++;
}else if(sum<target){
j++;
sum += j;
}else{ //==
int []arr = new int[j-i+1];
for(int k=i,q=0; k<=j; k++,q++) arr[q] = k;
list.add(arr);
sum += ++j;
}
}
int res[][] = new int[list.size()][];
for(i=0; i<list.size(); i++)
res[i] = list.get(i);
return res;
}
输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。
public int[] twoSum(int[] nums, int target) {
int i = 0, j = nums.length - 1;
while (i < j - 1) {
if (nums[i] + nums[j] < target)
i++;
else if (nums[i] + nums[j] > target)
j--;
else //==
break;
}
return new int[]{nums[i], nums[j]};
}
一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
public int[] singleNumbers(int[] nums) {
int tmp = 0;
for (int i = 0; i < nums.length; i++)
tmp = tmp ^ nums[i];
int one = tmp & (-tmp);
int res1 = 0, res2 = 0;
for (int i = 0; i < nums.length; i++)
if ((nums[i] & one) == one)
res1 ^= nums[i];
else
res2 ^= nums[i];
return new int[]{res1, res2};
}
输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。
public boolean isBalanced(TreeNode root) {
if(root==null)
return true;
if(Math.abs(maxDepth(root.left)-maxDepth(root.right))>1)
return false;
return isBalanced(root.left) && isBalanced(root.right);
}
public int maxDepth(TreeNode root) {
if(root==null)
return 0;
return Math.max(maxDepth(root.left),maxDepth(root.right))+1;
}
public int maxDepth(TreeNode root) {
if(root==null)
return 0;
return Math.max(maxDepth(root.left),maxDepth(root.right))+1;
}
给定一棵二叉搜索树,请找出其中第k大的节点。
//非递归中序遍历
public int kthLargest(TreeNode root, int k) {
Stack<TreeNode> stack = new Stack<>();
TreeNode tmp = root;
int count = 0;
while(tmp!=null || !stack.empty()){
while(tmp!=null){
stack.add(tmp);
tmp = tmp.right;
}
TreeNode node = stack.pop();
count++;
if(count==k) return node.val;
tmp = node.left;
}
return -1;
}
一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。
public int missingNumber(int[] nums) {
int left=0, right=nums.length-1, mid;
while(left<=right){
mid = (left+right)/2;
if(nums[mid]==mid) left = mid+1;
else right = mid-1;
}
return left;
}
统计一个数字在排序数组中出现的次数。
public int search(int[] nums, int target) {
int res=0, left = 0, right = nums.length-1, mid=0;
while(left<=right){
mid = (left+right)/2;
if(nums[mid]>target)
right = mid-1;
else if(nums[mid]<target)
left = mid+1;
else{
res++;
break;
}
}
left = mid-1;
while(left>=0 && nums[left--]==target) res++;
right = mid+1;
while(right<nums.length && nums[right++]==target) res++;
return res;
}
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
Stack<ListNode> stackA = new Stack<>();
Stack<ListNode> stackB = new Stack<>();
ListNode tmpA = headA, tmpB = headB, res = null;
while(tmpA!=null) {
stackA.push(tmpA);
tmpA = tmpA.next;
}
while(tmpB!=null) {
stackB.push(tmpB);
tmpB = tmpB.next;
}
if(stackA.empty() || stackB.empty())
return null;
while(!stackA.empty() && !stackB.empty() && stackA.peek()==stackB.peek()){
res = stackA.pop();
stackB.pop();
}
return res;
}
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
private int res = 0;
public int reversePairs(int[] nums) {
mergeSort(nums,0,nums.length-1,new int[nums.length]);
return res;
}
private void mergeSort(int[] nums, int s, int e, int[] tmp) {
if(s>=e)
return;
int mid = (s+e)/2;
mergeSort(nums, s, mid, tmp);
mergeSort(nums, mid+1, e, tmp);
merge(nums,s,mid,e,tmp);
}
private void merge(int[] nums, int s, int mid, int e, int[] tmp) {
int i=s,j=mid+1,k=s;
while(i<=mid && j<=e){
if(nums[i]<=nums[j])
tmp[k++] = nums[i++];
else{
tmp[k++] = nums[j++];
res += mid-i+1;
}
}
while(i<=mid)
tmp[k++] = nums[i++];
while (j<=e)
tmp[k++] = nums[j++];
for(i=s; i<=e; i++)
nums[i] = tmp[i];
}
在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。
public char firstUniqChar(String s) {
LinkedHashMap<Character, Integer> map = new LinkedHashMap<>();
for(int i=0; i<s.length(); i++){
char c = s.charAt(i);
if(map.containsKey(c))
map.put(c,map.get(c)+1);
else
map.put(c,1);
}
for(char c : map.keySet())
if(map.get(c)==1)
return c;
return ' ';
}
我们把只包含因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。
public int nthUglyNumber(int n) {
int p2=0,p3=0,p5=0,index=0;
int []arr = new int[n];
arr[index++] = 1;
while(index<n){
int tmp = Math.min(arr[p2]*2,Math.min(arr[p3]*3,arr[p5]*5));
if(tmp==arr[p2]*2) p2++;
if(tmp==arr[p3]*3) p3++;
if(tmp==arr[p5]*5) p5++;
arr[index++] = tmp;
}
return arr[n-1];
}
请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
public int lengthOfLongestSubstring(String s) {
HashMap<Character, Integer> map = new HashMap<>();
int max = 0;
for(int head=0,tail=0; tail<s.length(); tail++){
if(map.containsKey(s.charAt(tail))){
head = Math.max(map.get(s.charAt(tail))+1,head);
}
map.put(s.charAt(tail),tail);
max = Math.max(tail-head+1,max);
}
return max;
}
在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物?
//动态规划 f(i, j) = max{f(i - 1, j), f(i, j - 1)} + grid[i][j]
public int maxValue(int[][] grid) {
for(int i=0; i<grid.length; i++){
for(int j=0; j<grid[0].length; j++){
int max = -1;
if(i==0&&j==0) continue;
if(i-1>=0) max = grid[i-1][j];
if(j-1>=0) max = max>grid[i][j-1]?max:grid[i][j-1];
grid[i][j] += max;
}
}
return grid[grid.length-1][grid[0].length-1];
}
//超时
private int res = 0;
private int n,m;
public int maxValue(int[][] grid) {
if(grid==null || grid.length==0)
return 0;
n = grid.length; m=grid[0].length;
dfs(grid,0,0,0);
return res;
}
private void dfs(int[][] arr, int x, int y, int sum) {
if(x==n-1 && y==m-1){
sum += arr[x][y];
res = res>sum?res:sum;
return;
}
if(x+1<n)
dfs(arr,x+1,y,sum+arr[x][y]);
if(y+1<m)
dfs(arr,x,y+1,sum+arr[x][y]);
}
给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。
public int translateNum(int num) {
if(num<=9)
return 1;
if(num%100<=9 || num%100>=26)
return translateNum(num/10);
return translateNum(num/10)+translateNum(num/100);
}
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
public String minNumber(int[] nums) {
return Arrays.stream(nums).mapToObj(num->num+"")
.sorted((i,j)->(i+j).compareTo(j+i))
.collect(Collectors.joining());
}
数字以0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等。
请写一个函数,求任意第n位对应的数字。
public int findNthDigit(int n) {
if(n<10)
return n;
long k=1,sum=n,s= (long) (Math.pow(10,k-1)*9);
while(sum>s){
sum -= s;
k++;
s = (long) (Math.pow(10,k-1)*9)*k;
}
String res = (int)(Math.pow(10,k-1)+(sum-1)/k) +"";
int mod = (int)((sum-1) % k);
return res.charAt(mod)-'0';
}