算法-双指针

算法-双指针

 

    心灰尽,有发未全僧。

 

简介:算法-双指针

一、和为S 的两个数字

1、题目描述

在有序数组中找出两个数,使得和为给定的数 S。如果有多对数字的和等于 S,输出两个数的乘积最小的。

2、解题思路

使用双指针,一个指针指向元素较小的值,一个指针指向元素较大的值。指向较小元素的指针从头向尾遍历,指向较大元素的指针从尾向头遍历。

  • 如果两个指针指向元素的和 sum == target,那么这两个元素即为所求。
  • 如果 sum > target,移动较大的元素,使 sum 变小一些;
  • 如果 sum < target,移动较小的元素,使 sum 变大一些。

3、代码示例

 1 import java.util.ArrayList;
 2 public class Solution {
 3     public ArrayList<Integer> FindNumbersWithSum(int [] array, int sum) {
 4         ArrayList<Integer> list = new ArrayList<>();
 5         int i = 0;
 6         int j = array.length - 1;
 7         while(i < j){
 8             if(array[i] + array[j] == sum){
 9                 list.add(array[i]);
10                 list.add(array[j]);
11                 break;
12             }else if(array[i] + array[j] < sum){
13                 i++;
14             }else{
15                 j--;
16             }
17         }
18         return list;
19     }
20 }

View Code

 二、和为S 的连续正数序列

1、题目描述

输出所有和为 S 的连续正数序列。例如和为 100 的连续序列有:

[9, 10, 11, 12, 13, 14, 15, 16]
[18, 19, 20, 21, 22]

2、解题思路

前缀和

对于求一个区间和,一贯的优化技巧是使用前缀和。比如:
图片说明
sum[i]表示前i个数的和。比如sum[1] = 1,表示前一个数的和为1sum[2] = 3, 表示前2个数的和为3。

现在我们要求区间[2,4]表示求第2,3,4个数的和,就等于sum[4] - sum[1] = 9

在代码中用一个变量来模拟这个前缀和。

 1 import java.util.ArrayList;
 2 public class Solution {
 3     public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
 4        ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
 5         for(int i = 1; i < sum; i++){
 6             int temp = 0;
 7             int j = i;
 8             while(temp < sum){
 9                 temp += j;
10                 j++;
11             }
12             if(temp == sum){
13                 // 满足条件则拼装数据
14                 ArrayList<Integer> list = new ArrayList<Integer>();
15                 for(int k = i; k < j; k++){
16                     list.add(k);
17                 }
18                 result.add(list);
19             }         
20         }
21          return result;
22     }
23 }

View Code

 三、翻转单词顺序列

1、题目描述

Input:
"I am a student."

Output:
"student. a am I"

2、解题思路

借助一些Java 自带的API 就很容易实现。

 1 import java.util.*;
 2 
 3 public class Solution {
 4     public String ReverseSentence(String str) {
 5         String[] split = str.split(" ");
 6         List<Object> list = new ArrayList<>();
 7         StringBuilder sb = new StringBuilder();
 8         for(int i = 0; i < split.length; i++){
 9             list.add(split[i]);
10         }
11         Collections.reverse(list);  // 借助集合翻转API
12         Iterator<Object> iterator = list.iterator();
13         while (iterator.hasNext()){
14             sb.append(iterator.next()).append(" ");
15         }
16         return sb.toString().trim();  // 除去最后一个append 加上去的空格
17     }
18 }

View Code

 四、左旋转字符串

1、题目描述

将字符串 S 从第 K 位置分隔成两个子字符串,并交换这两个子字符串的位置。

Input:
S="abcXYZdef"
K=3

Output:
"XYZdefabc"

2、解题思路

使用Java API 的substring 就很简单了。

 1 public class Solution {
 2     public String LeftRotateString(String str, int n) {
 3         int length = str.length();
 4         if(n > length){
 5             return "";
 6         }
 7         String substring1 = str.substring(0, n);  // substring 左闭右开
 8         String substring2 = str.substring(n);
 9         return substring2 + substring1;
10     }
11 }

View Code

 

 

 

 

 

      心灰尽

有发未全僧