1. 两数之和
题目:
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
【解法一】暴力法
通过用front指针指向其中一个元素,end指针遍历每个元素,判断是否有两个数字可以相加结果等于target。
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] result=new int[2];
for(int front=0;front<nums.length-1;front++){
for(int end=front+1;end<nums.length;end++){
if(nums[front]+nums[end]==target){
return new int[]{front,end};
}
}
}
return new int[]{-1};
}
}
该算法为暴力遍历,时间复杂度高。
【解法二】哈希表法
数组的值存入哈希表的Key值;数组的下标存入哈希表的Value值。
遍历数组,从哈希表中获取(目标值-数组值)结果,如果查询到,则返回数组下标值
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer,Integer> map=new HashMap<>();
for(int i=0;i<nums.length;i++){
if(map.containsKey(target-nums[i])){
return new int[]{map.get(target-nums[i]),i};
}
map.put(nums[i],i);
}
return new int[-1];
}
}
2. 两数相加
题目:
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以0 开头。
【解法一】栈
分别将两个链表转入栈出,再取出,获得正常的数据,将两个数据相加得到结果,再将结果转为链表。该方式在一定条件上可以获取结果,但当数据较长时,会出现溢出,导致结果错误。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
Stack<Integer> stack1=new Stack<>();
Stack<Integer> stack2=new Stack<>();
// 将l1转入栈
while(l1!=null){
stack1.push(l1.val);
l1=l1.next;
}
// 将l2转入栈
while(l2!=null){
stack2.push(l2.val);
l2=l2.next;
}
//获取l1
int temp1=0;
while(!stack1.empty()){
temp1=temp1*10+stack1.pop();
}
//获取l2
int temp2=0;
while(!stack2.empty()){
temp2=temp2*10+stack2.pop();
}
//得到总和
int temp=temp1+temp2;
ListNode head=null;
ListNode tail=null;
while(temp!=0){
if(head==null){
head=new ListNode(temp%10);
tail=head;
}else{
tail.next=new ListNode(temp%10);
tail=tail.next;
}
temp/=10;
}
if(head==null){
return new ListNode(0);
}
return head;
}
}
为此,需要采用另一种方式。
【解法二】模拟
由于取出数据再计算可能导致溢出,因此,我们不取出数据,而是直接对每一个结点的值进行计算,如果有进位,则保存进位的值,然后把计算结果放入新结点中。
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode head = null, tail = null;
int carry = 0;
while (l1 != null || l2 != null) {
int n1 = l1 != null ? l1.val : 0;
int n2 = l2 != null ? l2.val : 0;
int sum = n1 + n2 + carry;
if (head == null) {
head = tail = new ListNode(sum % 10);
} else {
tail.next = new ListNode(sum % 10);
tail = tail.next;
}
carry = sum / 10;
if (l1 != null) {
l1 = l1.next;
}
if (l2 != null) {
l2 = l2.next;
}
}
if (carry > 0) {
tail.next = new ListNode(carry);
}
return head;
}
}
总结:在遇到数计算时,要考虑是否会发生溢出,如果溢出会导致数据错误。如果找不到取值范围符合要求的数据类型,则可以考虑换一种思路,不要卡死在计算上。