和为s的连续正数序列
剑指 Offer 57 - II. 和为s的连续正数序列 - 力扣(Leetcode)
题目要求
输入一个正整数 target
,输出所有和为 target
的连续正整数序列(至少含有两个数)。
序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
例子:
1 2 3 4 5 输入:target = 9 输出:[[2 ,3 ,4 ],[4 ,5 ]] 输入:target = 15 输出:[[1 ,2 ,3 ,4 ,5 ],[4 ,5 ,6 ],[7 ,8 ]]
提示:
1 <= target <= 10^5
思路分析
滑动窗口
定义i
和j
两个指针,同时从下标为0的位置开始,现在滑动窗口只有一个值;
若当前窗口内的值小于target,就将j++
;窗口每移动一次就进行判断;
若当前窗口内的值大于target,就将i++
;窗口每移动一次就进行判断;
若当前窗口内的值等于target,就将窗口内所有的值保存起来;
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class Solution { public int [][] findContinuousSequence(int target) { List<int []> res = new ArrayList <>(); int i = 1 , j = 1 ; int sum = 1 ; while (i <= target / 2 ){ if (sum < target){ j++; sum = sum + j; }else if (sum > target){ sum = sum - i; i++; }else { int [] temp = new int [j - i +1 ]; int index = 0 ; for (int k = i ; k <= j;k++){ temp[index++] = k; } sum = sum - i; i++; j++; sum = sum + j; res.add(temp); } } return res.toArray(new int [res.size()][]); } }
翻转单词顺序
剑指 Offer 58 - I. 翻转单词顺序 - 力扣(Leetcode)
题目要求
输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student. “,则输出"student. a am I”。
例子:
1 2 3 4 5 6 7 8 9 10 输入: "the sky is blue" 输出: "blue is sky the" 输入: " hello world! " 输出: "world! hello" 解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。 输入: "a good example" 输出: "example good a" 解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个
提示:
无空格字符构成一个单词。
输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
思路分析
从后先前,将单词拆分开,然后进行反转即可;
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution { public String reverseWords (String s) { if (s == null || s.length() <= 0 ){ return s; } s = s.trim(); StringBuilder builder = new StringBuilder (); int i = s.length() - 1 , j = i; while (i >= 0 ){ while (i >= 0 && s.charAt(i) != ' ' ) i--; builder.append(s.substring(i+1 ,j+1 ) + " " ); while (i >= 0 && s.charAt(i) == ' ' ) i--; j = i; } return builder.toString().trim(); } }
左旋转字符串
剑指 Offer 58 - II. 左旋转字符串 - 力扣(Leetcode)
题目要求
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。
例子:
1 2 3 4 5 输入: s = "abcdefg" , k = 2 输出: "cdefgab" 输入: s = "lrloseumgh" , k = 6 输出: "umghlrlose"
提示:
1 <= k < s.length <= 10000
思路分析
使用StringBuilder进行拼接,先将k之后的部分拼接,然后再将k之前的拼接到后面即可;
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Solution { public String reverseLeftWords (String s, int n) { StringBuilder builder = new StringBuilder (); int len = s.length(); for (int i = n; i < len; i++){ builder.append(s.charAt(i)); } for (int i=0 ; i< n; i++){ builder.append(s.charAt(i)); } return builder.toString(); } }
滑动窗口的最大值
剑指 Offer 59 - I. 滑动窗口的最大值 - 力扣(Leetcode)
题目要求
给定一个数组 nums
和滑动窗口的大小 k
,请找出所有滑动窗口里的最大值。
例子:
1 2 3 4 5 6 7 8 9 10 11 12 输入: nums = [1 ,3 ,-1 ,-3 ,5 ,3 ,6 ,7 ], 和 k = 3 输出: [3 ,3 ,5 ,5 ,6 ,7 ] 解释: 滑动窗口的位置 最大值 --------------- ----- [1 3 -1 ] -3 5 3 6 7 3 1 [3 -1 -3 ] 5 3 6 7 3 1 3 [-1 -3 5 ] 3 6 7 5 1 3 -1 [-3 5 3 ] 6 7 5 1 3 -1 -3 [5 3 6 ] 7 6 1 3 -1 -3 5 [3 6 7 ] 7
提示:
你可以假设 k 总是有效的,在输入数组 不为空 的情况下,1 ≤ k ≤ nums.length
。
思路分析
队列
新建一个队列,通过不断扩大滑动窗口,每当滑动窗口出现一个值,就将它与队列顶部的元素进行比较,如果新的值比队列顶部的值大,就将队列的值都出队,然后将新的值放入队列;
如果比队列顶部值小,就将它加入到队列里;
当我们不断滑动窗口,还需要判断队列顶部的值是否还在窗口内,如果不在需要把它出队;
当滑动窗口达到最大值,就将队列顶部元素保存,每次滑动窗口移动,队列顶部的值若发生改变,也将其保存;
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class Solution { public int [] maxSlidingWindow(int [] nums, int k) { if (nums == null || nums.length <= 1 ){ return nums; } LinkedList<Integer> queue = new LinkedList <>(); int [] res = new int [nums.length - k +1 ]; int index = 0 ; for (int i=0 ;i<nums.length;i++){ while (!queue.isEmpty() && nums[queue.peekLast()] <= nums[i]){ queue.pollLast(); } queue.add(i); if (queue.peekLast() - k == queue.peek()){ queue.poll(); } if (i+1 >= k){ res[index++] = nums[queue.peek()]; } } return res; } }
队列的最大值
面试题59 - II. 队列的最大值 - 力扣(Leetcode)
题目要求
请定义一个队列并实现函数 max_value
得到队列里的最大值,要求函数max_value
、push_back
和 pop_front
的均摊 时间复杂度都是O(1)。
若队列为空,pop_front
和 max_value
需要返回 -1
例子:
1 2 3 4 5 6 7 8 9 输入: ["MaxQueue" ,"push_back" ,"push_back" ,"max_value" ,"pop_front" ,"max_value" ] [[],[1 ],[2 ],[],[],[]] 输出: [null ,null ,null ,2 ,1 ,2 ] 输入: ["MaxQueue" ,"pop_front" ,"max_value" ] [[],[],[]] 输出: [null ,-1 ,-1 ]
提示:
1 <= push_back,pop_front,max_value的总操作数 <= 10000
1 <= value <= 10^5
思路分析
从队列尾部插入元素时,可以提前取出队列中所有比这个元素小的元素,使得队列中只保留对结果有影响的数字。
等价于要求维护队列的单调递减性,即要保证每个元素前面都没有比他小的元素;
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 class MaxQueue { Queue<Integer> q; Deque<Integer> d; public MaxQueue () { q = new LinkedList <Integer>(); d = new LinkedList <Integer>(); } public int max_value () { if (d.isEmpty()){ return -1 ; } return d.peekFirst(); } public void push_back (int value) { while (!d.isEmpty() && d.peekLast() < value){ d.pollLast(); } d.offerLast(value); q.offer(value); } public int pop_front () { if (q.isEmpty()) { return -1 ; } int flag = q.poll(); if (flag == d.peekFirst()){ d.pollFirst(); } return flag; } }