编程练习题集——leetcode

目录

  • 一、数组
    • 1.1、简单
      • 第1题 可被 5 整除的二进制前缀
      • 第2题 两数之和
      • 第3题 删除排序数组中的重复项
      • 第3题 移动零
      • 第4题 多数元素
      • 第5题 按奇偶排序数组
      • 第6题 移除元素
      • 第7题 搜索插入位置
      • 第8题 合并两个有序数组
      • 第9题 丢失的数字
  • 二、数学
    • 2.1、简单
      • 第1题 整数反转
      • 第2题 回文数
      • 第3题 罗马数字转整数
    • 2.2 中等难度
      • 第1题
  • 三、字符串
    • 2.1 简单
      • 第1题 最长公共前缀
      • 第2题 有效的括号
      • 第3题 实现 strStr()
      • 第4题 最后一个单词的长度
  • 四、链表
    • 简单
    • 中等
      • 第1题 两数相加
      • 第2题 删除链表的倒数第 N 个结点

一、数组

1.1、简单

第1题 可被 5 整除的二进制前缀

给定由若干 0 和 1 组成的数组 A。我们定义 N_i:从 A[0] 到 A[i] 的第 i 个子数组被解释为一个二进制数(从最高有效位到最低有效位)。
返回布尔值列表 answer,只有当 N_i 可以被 5 整除时,答案 answer[i] 为 true,否则为 false。
示例1:
输入:[0,1,1]
输出:[true,false,false]
解释:
输入数字为 0, 01, 011;也就是十进制中的 0, 1, 3 。只有第一个数可以被 5 整除,因此 answer[0] 为真。
示例 2:
输入:[1,1,1]
输出:[false,false,false]
代码:

class Solution {
     
    public List<Boolean> prefixesDivBy5(int[] A) {
     
        List<Boolean> list=new ArrayList<Boolean>();
        int length =A.length;       //获取传入的数组的长度
        int a=0;                      //定义变量a用于存放余数
        for(int i=0;i<length;i++){
     
            a=((a<<1)+A[i])%5;          //向左移动1位       (二进制数)
            list.add(a==0);
        }
        return list;
    }
}

思路:设开始的余数为0,数组中的数对5取余,如果能被整除,则余数为0,如果不能不能被整除,就保留这个余数,下一次计算余数放在这个余数后,一直到这个余数为0

第2题 两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
代码:

class Solution {
     
    public int[] twoSum(int[] nums, int target) {
     
        for(int i=0;i<nums.length;i++){
     
            for(int j=0;j<nums.length;j++){
     
                if((nums[i]+nums[j])==target){
     				//判断有没有在下标i的情况下有数和他相加的接股票是target;
                    return new int[]{
     i,j};
                }
            }
        }
        return new int[0];						//没有的话就返回一个长度为0的数组
    }
}

思路:枚举这个数组,找到两个数的和为target的两个数,然后返回一个数组,数组中存有着两个数的下标。

第3题 删除排序数组中的重复项

给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
示例 1:
给定数组 nums = [1,1,2],
函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。
你不需要考虑数组中超出新长度后面的元素。
示例 2:
给定 nums = [0,0,1,1,1,2,2,3,3,4],
函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。
你不需要考虑数组中超出新长度后面的元素。
代码:

class Solution {
     
    public int removeDuplicates(int[] nums) {
     
    /*
		0,0,1,1,2,2
		i
			  j
	*/
        if(nums ==null|| nums.length == 0 ){
     
            return 0;
        }
        int i = 0;
        int j = 1;
        while(j < nums.length){
     
            if(nums[i] != nums[j]){
     
                i++;
                nums[i] = nums[j];
            }
            j++;
        }
        return i + 1;
    }
}

思路:定义一个写指针i,读指针j,i从0开始,j从1开始,j最大时就是数组长度减1,
j向后移动,直到j指向的值与i指向的值不相等时,将j指向的值赋给i+1这个位置,然后j向后移动,指向的值继续与写指针指向的值比较。

第3题 移动零

相关标签:数组、双指针
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
示例:
输入: [0,1,0,3,12]
输出: [1,3,12,0,0]

class Solution {
     
    public void moveZeroes(int[] nums) {
     
        int l = 0;
        int temp = 0;
        for (int r = 0;r < nums.length; r++){
     
            if (nums[r] != 0){
     
                temp = nums[i];
                nums[r] = nums [l];
                nums[l] = temp;
                l++;
            }
        }
    }
}

思路:先定义两个指针,r向右移动,若指向的数不为0,则与l指针指向的数交换位置,l指向的是最左边的那个0.
编程练习题集——leetcode_第1张图片

第4题 多数元素

给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入:[3,2,3]
输出:3
示例 2:
输入:[2,2,1,1,1,2,2]
输出:2

class Solution {
     
    public int majorityElement(int[] nums) {
     
        int m = nums[0]; int count = 1;
        for (int i = 1; i < nums.length; i++) {
      
            if (nums[i] == m) {
      count++; 
            } else {
      
                count--; 
                if (count == 0) {
     
                     m = nums[i]; 
                     count = 1; 
                } 
            } 
        }return m;
    }
}

思路:如果两个数不相等,那么就碰撞消亡吧,剩下的全部是同一个数,即答案。

第5题 按奇偶排序数组

给定一个非负整数数组 A,返回一个数组,在该数组中, A 的所有偶数元素之后跟着所有奇数元素。
你可以返回满足此条件的任何数组作为答案。
示例:
输入:[3,1,2,4]
输出:[2,4,3,1]
输出 [4,2,3,1],[2,4,1,3] 和 [4,2,1,3] 也会被接受。

class Solution {
     
    public int[] sortArrayByParity(int[] A) {
     
        int l = 0; int r = A.length - 1; 
        while (l < r) {
      
            //左奇右偶 
            if (A[l] % 2 == 1 && A[r] % 2 == 0) {
      
                int temp = A[l]; 
                A[l] = A[r]; 
                A[r] = temp; 
                //左偶右奇 
                } else if (A[l] % 2 == 0 && A[r] % 2 == 1) {
      
                    l++; r--;
                //左奇右奇 
                } else if (A[l] % 2 == 1 && A[r] % 2 == 1) {
      
                    r--; 
                } else {
      
                    l++;
                } 
        }
        return A;
    }
}

思路:定义两个指针,一个从左到右(l),另一个从右到左(r),如果左边指向的数是奇数右边指向的是偶数,则它们交换位置;如果左偶右奇,则两个指针均移动一次;如果左右都是奇数,则把左边的数已到右边,就是右边的指针移动一位让它与另一个数比较,左偶右偶与之类似考虑,

第6题 移除元素

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
示例 1:
输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。

class Solution {
     
    public int removeElement(int[] nums, int val) {
     
        int i = 0;
        for (int j= 0 ; j < nums.length ; j++){
     
            if(nums[j] != val){
     
                nums[i] = nums[j];
                i++;
            }
        }
        return i;
    }
}

思路:保留两个指针 ii 和 jj,其中 ii 是慢指针,jj 是快指针,当 nums[j]nums[j] 与给定的值相等时,递增 jj 以跳过该元素。只要 nums[j] !=val,我们就复制 nums[j]nums[j] 到 nums[i]nums[i] 并同时递增两个索引。

第7题 搜索插入位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
示例 1:
输入: [1,3,5,6], 5
输出: 2
示例 2:
输入: [1,3,5,6], 2
输出: 1
代码:

class Solution {
     
    public int searchInsert(int[] nums, int target) {
     
         int left = 0, right = nums.length - 1;
        while(left <= right) {
     
            int mid = (left + right) / 2;
            if(nums[mid] == target) {
     
                return mid;
            } else if(nums[mid] < target) {
     
                left = mid + 1;
            } else {
     
                right = mid - 1;
            }
        }
        return left;
    }
}

思路:二分查找,从两边开始查找,对比目标值和中间值,然后根据对比的结果移动两头的指针。

第8题 合并两个有序数组

给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。
初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。你可以假设 nums1 的空间大小等于 m + n,这样它就有足够的空间保存来自 nums2 的元素。
示例 1:
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
示例 2:
输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]
代码:

class Solution {
     
    public void merge(int[] nums1, int m, int[] nums2, int n) {
     
    System.arraycopy(nums2, 0, nums1, m, n);
    Arrays.sort(nums1);
    }
}

思路:先合并再排序。

第9题 丢失的数字

给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数。
示例 1:
输入:nums = [3,0,1]
输出:2
解释:n = 3,因为有 3 个数字,所以所有的数字都在范围 [0,3] 内。2 是丢失的数字,因为它没有出现在 nums 中。
示例 2:
输入:nums = [0,1]
输出:2
解释:n = 2,因为有 2 个数字,所以所有的数字都在范围 [0,2] 内。2 是丢失的数字,因为它没有出现在 nums 中。
示例 3:
输入:nums = [9,6,4,2,3,5,7,0,1]
输出:8
解释:n = 9,因为有 9 个数字,所以所有的数字都在范围 [0,9] 内。8 是丢失的数字,因为它没有出现在 nums 中。
代码:

class Solution {
     
    public int missingNumber(int[] nums) {
     
        int[] results = new int[nums.length+1];
        for (int num : nums) 
            results[num] = num;
        for (int i = 0; i < results.length; i++) {
     
            if(results[i] == 0 && i != 0) {
     
                return i;
            }
        }
        return 0;
    }
}

思路:创建一个长度为nums.length+1的数组result,遍历数组nums,填充数组result,给对应的值给对应下标,遍历数组result,判断(没有被赋值的下标就是缺的数)返回,(思想与计数排序类似)

二、数学

2.1、简单

第1题 整数反转

给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。

假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231, 231 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。
示例 :
输入:x = -123
输出:-321
代码:

class Solution {
     
    public int reverse(int x) {
     
        int temp = 0;
        while (x != 0) {
     
            int tail = x % 10;           //取最后一位数
            x /= 10;                     //把最后一位数去掉,
            if (temp > Integer.MAX_VALUE/10 || (temp == Integer.MAX_VALUE / 10 && tail > 7)) return 0;  //判断溢出
            if (temp < Integer.MIN_VALUE/10 || (temp == Integer.MIN_VALUE / 10 && tail < -8)) return 0;
            temp = temp * 10 + tail;        //temp全部左移1位然后把之前取出的最后一位tail加在temp后面
        }
        return temp;
    }
}

temp = temp * 10 + tail;时会导致溢出

编程练习题集——leetcode_第2张图片

第2题 回文数

判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
示例 1:
输入: 121
输出: true
示例 2:
输入: -121
输出: false
解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
代码:

class Solution {
     
    public boolean isPalindrome(int x) {
     
        int temp = 0;			//存临时的数字
        int a = x; 
        if(x>=0){
     
            while(a!=0){
     
                temp = temp * 10 + a % 10;
                a/=10;
            }
            return temp == x?true:false;
        }
        else{
     
            return false;
        }
    }
}

思路:首先判断它是否是负数,如果是负数的话,那么它一定不是回文数。如果不是负数的话,则将其倒序数值计算出来,然后比较和原数值是否相等。声明temp用来暂存数字,将传入的参数值x的副本a对10取余然后加在temp的后面,a自除10以方便下次取的余数是前面一位,一直自除到商为0时表面数字的位数获取完毕,退出这个循环。然后让获得的数字temp与传入的参数x进行比较。

第3题 罗马数字转整数

标签:数学、字符串
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000

例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

  • I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
  • X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
  • C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
    给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。
    代码:
class Solution {
     
    public int romanToInt(String s) {
     
        String str=s.toUpperCase(); 		//全部转化为大写
        HashMap<Character,Integer> map=new HashMap();		//hashmap存值
        map.put('I',1);
        map.put('V',5);
        map.put('X',10);
        map.put('L',50);
        map.put('C',100);
        map.put('D',500);
        map.put('M',1000);
        int sum = 0;
        int preNum = map.get(str.charAt(0));			//定义上一个数字,初始值为第一个字符的数值
        for (int i = 1; i < str.length(); i++){
     
            int num = map.get(str.charAt(i));
            if (preNum < num){
     
                sum -= preNum;
            }else{
     
                sum += preNum;
            }
            preNum = num;
        }
        sum += preNum;
        return sum;
    }
}
  • 罗马数字由 I,V,X,L,C,D,M 构成;
  • 当小值在大值的左边,则减小值,如 IV=5-1=4;
  • 当小值在大值的右边,则加小值,如 VI=5+1=6;
  • 右值永远为正,因此最后一位必然为正。
    思路:

在遍历时往后看多一位,对比当前位与后一位的大小关系,从而确定当前位是加还是减法(前面位小则减去前位,否则加上前面位)。当没有下一位时,做加法即可。
也可保留当前位的值,当遍历到下一位的时,对比保留值与遍历位的大小关系,再确定保留值为加还是减。最后一位做加法即可。

2.2 中等难度

第1题

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例 1:
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
示例 2:
输入:l1 = [0], l2 = [0]
输出:[0]
示例 3:
输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]
代码:

class Solution {
     
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
     
        int i = 0;		//进位值
        ListNode head = null, l3 = null;
        while(l1 != null || l2 != null){
     
            int i1 = (l1 == null) ? 0 : l1.val;
            int i2 = (l2 == null) ? 0 : l2.val;
            int sum = i1 + i2 + i;
            i = sum / 10;
            int i3 = sum % 10;
            if(l3 == null){
     
                head = l3 = new ListNode(i3);
            }else{
     
                l3.next = new ListNode(i3);
                l3 = l3.next;
            }
            if (l2 != null){
     
                l2 = l2.next;
            }         
            if (l1 != null){
     
                l1 = l1.next;
            }          
        }
        if(i > 0){
     
            l3.next = new ListNode(i);  
        }
        return head;
    }
}

思路:首先定义一个进位变量i,初始值为0;定义两个ListkedNode变量,head指向头部,l3指向尾部;遍历链表了l1和l2,只要有一个的节点不为空就继续遍历;若l1或者l2其中之一的节点为空则这个节点对应的加数值为0;求出进位值i和当前位置的值i3,将当前位置的值加入到链表中;到最后判断进位值是否大于0,大于0表示多一位数;

三、字符串

2.1 简单

第1题 最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 “”。
示例 1:
输入:strs = [“flower”,“flow”,“flight”]
输出:“fl”
示例 2:
输入:strs = [“dog”,“racecar”,“car”]
输出:""
解释:输入不存在公共前缀。

代码:

class Solution {
     
    public String longestCommonPrefix(String[] strs) {
     
    if (strs == null || strs.length == 0) {
     
                return "";
            }
            String prefix = strs[0];
            int count = strs.length;
            for (int i = 1; i < count; i++) {
     
                prefix = longestCommonSubstring(prefix, strs[i]);
                if (prefix.length() == 0) {
     
                    break;
                }
            }
            return prefix;
    }

    public static String longestCommonSubstring(String s1,String s2){
     
        String str = "";
        if(s1.length()<s2.length())
        {
     
            String s3=s1;
            s1=s2;
            s2=s3;
        }
        for (int i = 0 ;i < s2.length(); i++){
     
            if (s2.charAt(i) == s1.charAt(i)){
     
                str += String.valueOf(s2.charAt(i));
            }else{
     
                break;
            }
       }
        return str;
    }
}

思路:先求前两个字符串的公共前缀,再用这个公共前缀和第三个字符串求公共前缀,以此类推,但是当还没循环完就得到公共前缀为“”的话,则提前结束循环,返回字符串“”

第2题 有效的括号

示例 1:
输入: “()[]{}”
输出: true
示例 2:
输入: “(]”
输出: false
代码:

class Solution {
     
    public boolean isValid(String s) {
     
         Stack<Character> stack = new Stack<>();
    char[] chars = s.toCharArray();
    //遍历所有的元素
    for (char c : chars) {
     
        //如果是左括号,就把他们对应的右括号压栈
        if (c == '(') {
     
            stack.push(')');
        } else if (c == '{') {
     
            stack.push('}');
        } else if (c == '[') {
     
            stack.push(']');
        } else if (stack.isEmpty() || stack.pop() != c) {
     
            //否则就只能是右括号。
            //1,如果栈为空,说明括号无法匹配。
            //2,如果栈不为空,栈顶元素就要出栈,和这个右括号比较。
            //如果栈顶元素不等于这个右括号,说明无法匹配,
            //直接返回false。
            return false;
        }
    }
    //最后如果栈为空,说明完全匹配,是有效的括号。
    //否则不完全匹配,就不是有效的括号
    return stack.isEmpty();
    }
}

思路:
遍历所有的括号,

  • 如果遇到了左括号,就把对应的右括号压栈(比如遇到了字符’(’,就把字符’)'压栈)。
  • 如果遇到了右括号
    • 查看栈是否为空,如果为空,说明不能构成有效的括号,直接返回false。
    • 如果栈不为空,栈顶元素出栈,然后判断出栈的这个元素是否等于这个右括号,如果不等于,说明不匹配,直接返回false。如果匹配,就继续判断字符串的下一个字符。
  • 最后如果栈为空,说明是完全匹配,是有效的括号,否则如果栈不为空,说明不完全匹配,不是有效的括号。

第3题 实现 strStr()

给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。
示例 1:
输入: haystack = “hello”, needle = “ll”
输出: 2
代码:

class Solution {
     
    public int strStr(String haystack, String needle) {
     
        if(needle.equals("")){
     
            return 0;
        }
        int hL = haystack.length();
        int nL = needle.length();
        for (int i = 0; i < hL-nL+1; i++){
     
            if (haystack.substring(i,i + nL).equals(needle)){
     
                return i;
            }
        }
        return -1;
    }
}

思路:从第0个字符开始找needle长度的子串,如果找的的子串与needle相等,则返回这个位置。

第4题 最后一个单词的长度

给定一个仅包含大小写字母和空格 ’ ’ 的字符串 s,返回其最后一个单词的长度。如果字符串从左向右滚动显示,那么最后一个单词就是最后出现的单词。
如果不存在最后一个单词,请返回 0 。
说明:一个单词是指仅由字母组成、不包含任何空格字符的 最大子字符串
示例:
输入: “Hello World”
输出: 5

代码:

class Solution {
     
    public int lengthOfLastWord(String s) {
     
        int count = 0;
        for (int i = s.length() - 1; i >= 0; i--){
     
            if (s.charAt(i) == ' ' && count == 0){
     
                continue;
            }else if(s.charAt(i) == ' '){
     
                break;
            }
            count++;
        }
        return count;
    }
}

思路:从后向前遍历字符串,如果最后的是空格就跳过当前循环,如果是字符就count自加一,当遇到空格是跳出此次循环,这是count记录的数就是最后一个代词的长度。

四、链表

简单

中等

第1题 两数相加

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例 1:
编程练习题集——leetcode_第3张图片

输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
示例 2:

输入:l1 = [0], l2 = [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) {
     
        int i = 0;
        ListNode head = null, l3 = null;
        while(l1 != null || l2 != null){
     
            int i1 = (l1 == null) ? 0 : l1.val;
            int i2 = (l2 == null) ? 0 : l2.val;
            int sum = i1 + i2 + i;
            i = sum / 10;
            int i3 = sum % 10;
            if(l3 == null){
     
                head = l3 = new ListNode(i3);
            }else{
     
                l3.next = new ListNode(i3);
                l3 = l3.next;
            }
            if (l2 != null){
     
                l2 = l2.next;
            }         
            if (l1 != null){
     
                l1 = l1.next;
            }          
        }
        if(i > 0){
     
            l3.next = new ListNode(i);  
        }
        return head;
    }
}

解释:当指向链表节点的指针都不为空时,对应指针的节点值相加,如果相加有进位,用一个变量暂时存储,用于下一次两节点值相加时在把进位值加进去。若有一链表指向null那么它所对应的值就是0(即+0)。当两条链表都到末尾后时结束循环,判断进位不变量是否大于0,如果有进位就再增加一个值为进位值的节点。最后返回这个链表的头节点。

第2题 删除链表的倒数第 N 个结点

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
进阶:你能尝试使用一趟扫描实现吗?
示例 1:
编程练习题集——leetcode_第4张图片

输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
示例 2:
输入:head = [1], n = 1
输出:[]
代码:

/**
 * 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 removeNthFromEnd(ListNode head, int n) {
     
                ListNode dummy = new ListNode(0, head);
        ListNode first = head;
        ListNode second = dummy;
        for (int i = 0; i < n; ++i) {
     
            first = first.next;
        }
        while (first != null) {
     
            first = first.next;
            second = second.next;
        }
        second.next = second.next.next;
        ListNode ans = dummy.next;
        return ans;

        // Map map = new HashMap();
        // int index = 0;
        // ListNode p = head;
        // while(p != null){
     
        //     map.put(index++,p);        
        //     p = p.next;
        // }
        // if(n <= 0 || n > index){
     
        //     return head;
        // }

        // if(index == 1){
     
        //     head = null;
        // }else if(index == n){
     
        //     head = head.next;
        // }else{
     
        //     ListNode cur =(ListNode) map.get(index - n);
        //     ListNode pre =(ListNode) map.get(index - n -1);
        //     pre.next = cur.next;
        // }
        // return head;
    }
}

解释:①定义两个指针first和second,first最开始指向head,second最开始指向head前一个节点,second的作用值指向被删除节点的前一个节点,first先向后移动n次,然后first和second一起向后移动,直到first指向null。此时second的next为它的后一个的后一个节点。最后返回head。
②遍历一次链表,然后用一个map集合存起来,按顺序存key值,这是就可以当一个数组来看。

此文章题目来源:力扣(LeetCode)

你可能感兴趣的:(练习)