《剑指offer》刷题——【面试中的各项能力】面试题57:和为s的数字(java实现)

(一)题目一:和为s的两个数字

一、题目描述

输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于
S,输出两个数的乘积最小的。

二、题目分析

方法一:双循环-O(n^2)

  • 先在数组中固定一个数字
  • 再依次判断数组中其余的n-1个数字与它的和是不是等于s

方法二:双指针-O(n)

  • 双指针,一个指向头,一个指向尾
  • 求指针指向的两个数字的和:
    • 若和=s,则指针指向的两个数字为所求
    • 若和>s,则尾指针向前移动1步
    • 若和<s,则头指针向后移动1步
      在这里插入图片描述

代码实现

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
        
		ArrayList<Integer> list = new ArrayList<Integer>();//存放结果集
		// 先判断特殊情况:数字少于两个时
		if (array.length < 2 || array == null) {
			return list;
		}
		// 获取数组的长度
		int len = array.length;
		int start = 0;//头指针
		int end = len - 1;//尾指针
        //遍历数组
		while (start < end) {
            //判断两个指针指向的两个数字的和是否等于指定数字,若等于则将数字添加到list中
            //找到第一组和等于指定数字,即为乘积最小的
			if (array[start] + array[end] == sum) {
				list.add(array[start]);
				list.add(array[end]);
				return list;
				
			}
            //若两个数字的和大于指定数字,则将尾指针向前移动一步
			if (array[start] + array[end] > sum) {
				end--;
			}
            //若两个数字的和小于指定数字,则将头指针向后移动一步
			if (array[start] + array[end] < sum) {
				start++;
			}
		}
		return list;
    }
}

参考资料

(二)题目二:和为s的连续正数序列

一、题目描述

输入一个正数s,打印出所有和为s的连续正数序列(至少含有两个数)。
例如,输入15,打印出3个连续的序列1~5, 4~6, 7~8

二、题目分析

  • 双指针,small,big分别指向序列中最小值和最大值
  • 初始化:small=1, big=2
  • 若small ~big的序列的和大于s,则增大small
  • 若small ~big的序列的和小于s,则增大big

三、代码实现


import java.util.ArrayList;
public class Solution {
    public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
        
        ArrayList<ArrayList<Integer> > result = new ArrayList<>();//存放结果
        //两个起点,相当于动态窗口的两边,根据其窗口内的值的和来确定窗口的位置和大小
        int small = 1;
        int big = 2;
      
        //遍历,small要小于big
        while(big > small){
            //当前序列和
            int curS = (small + big)*(big-small+1)/2;
            //若当前序列和等于指定数字,那么就将窗口范围的所有数添加进结果集
            if(curS == sum){
                ArrayList<Integer> list = new ArrayList<>();//存放和为s的连续序列中的数字
                for(int i=small; i<=big; i++){
                    list.add(i);
                }
                result.add(list);//将此序列添加到结果集中
                //small后移
                small++;
            
            }
            //若当前和小于s,则将big后移
            else if(curS < sum){
                big++;
            }
            //若当前和大于s,则将small后移
            else{
                small++;
            }
        }
        return result;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值