Leetcode(easy Double pointer)

it2024-08-18  49

Leetcode(easy Double pointer)

Leetcode 双指针简单题目

26 删除排序数组中的重复项

class Solution{ public int removeDuplicates(int[] nums){ // step代表慢指针 int step = 0; // 这里面的i就相当于快指针 for(int i = 1;i<nums.length;i++){ if(nums[i] != nums[step]){ // 满指针后移 存放i指向的不同的元素 step++; nums[step] = nums[i]; } } return step+1; } }

27 移除元素

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

28 实现strStr()

实现 strStr() 函数。给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。

class Solution { public int strStr(String haystack, String needle) { int L = needle.length(), n = haystack.length(); if (L == 0) return 0; int pn = 0; while (pn < n - L + 1) { while (pn < n - L + 1 && haystack.charAt(pn) != needle.charAt(0)) ++pn; int currLen = 0, pL = 0; while (pL < L && pn < n && haystack.charAt(pn) == needle.charAt(pL)) { ++pn; ++pL; ++currLen; } if (currLen == L) return pn - L; pn = pn - currLen + 1; } return -1; } }

88 合并两个有序数组

给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。

class Solution { public void merge(int[] nums1, int m, int[] nums2, int n) { int i = m-1; int j = n-1; int index = m+n-1; while(i>-1&&j>-1){ if(nums1[i]<nums2[j]){ nums1[index] = nums2[j]; j--; index--; }else{ nums1[index] = nums1[i]; i--; index--; } } while(i>-1){ nums1[index] = nums1[i]; i--; index--; } while(j>-1){ nums1[index] = nums2[j]; j--; index--; } } }

125 验证回文串

给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。

class Solution { public boolean isPalindrome(String s) { int n = s.length(); int left = 0, right = n - 1; while (left < right) { while (left < right && !Character.isLetterOrDigit(s.charAt(left))) { ++left; } while (left < right && !Character.isLetterOrDigit(s.charAt(right))) { --right; } if (left < right) { if (Character.toLowerCase(s.charAt(left)) != Character.toLowerCase(s.charAt(right))) { return false; } ++left; --right; } } return true; } }

141 环形链表

给定一个链表,判断链表中是否有环。

/** * Definition for singly-linked list. * class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ public class Solution { public boolean hasCycle(ListNode head) { if(head == null || head.next == null) return false; ListNode fast = head; ListNode slow = head; while(fast!=null && fast.next !=null && slow!=null){ // 一定要把if(fast == slow) return 放在移动过指针的下面,不然的话初始状态肯定是相等的 slow = slow.next; fast = fast.next.next; if(fast == slow) return true; } return false; } }

167. 两数之和 II - 输入有序数组

给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。

class Solution { public int[] twoSum(int[] numbers, int target) { // 设置两个指针 int i = 0; int j = numbers.length - 1; boolean flag = true; while(flag){ if(numbers[i] + numbers[j] > target) j--; else if(numbers[i] + numbers[j] < target) i++; else return new int[]{i+1,j+1}; } return new int[2]; } }

234 回文链表

请判断一个链表是否为回文链表。

/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public boolean isPalindrome(ListNode head) { if(head == null || head.next == null) return true; ListNode pre = head; ListNode cur = head; int len = 0; while(pre != null){ pre=pre.next; len++; } pre = head; int mid = (len%2)==1?(len/2+2):(len/2+1); while(mid-- >1) cur = cur.next; cur = reverse(cur); while(cur != null && pre != null){ if(pre.val != cur.val) return false; pre = pre.next; cur = cur.next; } return true; } // 将链表翻转,并返回翻转之后的头结点 public ListNode reverse(ListNode root){ if(root == null || root.next == null) return root; ListNode dummy = new ListNode(0); dummy.next = null; ListNode pre = root; ListNode cur = root.next; while(pre != null){ pre.next = dummy.next; dummy.next = pre; pre = cur; if(cur!=null) cur = cur.next; } return dummy.next; } }

283. 移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

class Solution { public void moveZeroes(int[] nums) { /** // 这种解法会导致非零元素的相对位置的改变 int i = 0; int j = nums.length-1; while(i<j){ // 正向找到0所在的下标 while(i<j && nums[i]!=0) i++; // 反向找到不为0的数字所在的下标 while(i<j && nums[j]==0) j--; int tmp = nums[i]; nums[i] = nums[j]; nums[j] = tmp; i++; j--; } */ if(nums==null) { return; } //第一次遍历的时候,j指针记录非0的个数,只要是非0的统统都赋给nums[j] int j = 0; for(int i=0;i<nums.length;++i) { if(nums[i]!=0) { nums[j++] = nums[i]; } } //非0元素统计完了,剩下的都是0了 //所以第二次遍历把末尾的元素都赋为0即可 for(int i=j;i<nums.length;++i) { nums[i] = 0; } } }

344. 反转字符串

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。 你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。

class Solution { public void reverseString(char[] s) { // 设置两个指针 int i = 0; int j = s.length-1; while(i<j){ char tmp = s[i]; s[i] = s[j]; s[j] = tmp; i++; j--; } } }

345. 反转字符串中的元音字母

编写一个函数,以字符串作为输入,反转该字符串中的元音字母

class Solution { public String reverseVowels(String s) { Set<Character> yuan = new HashSet<>(); String str = "aeiouAEIOU"; for(Character c:str.toCharArray()) yuan.add(c); // 设置两个指针,left和right,其中left指针从左向右查找元音字符,right从右向左查找元音字符, int left = 0; int right = s.length()-1; // 因为java无法对字符串进行直接的操作,这里我们将字符串s变为字符数组 char[] s2c = s.toCharArray(); // 遍历s2c while(left < right){ while(left < right && !yuan.contains(s2c[left])) left++; while(left < right && !yuan.contains(s2c[right])) right--; char temp = s2c[left]; s2c[left] = s2c[right]; s2c[right] = temp; // 交换完毕之后,让指针移动 left++; right--; } return String.valueOf(s2c); } }

349 两个数组的交集

题目:给定两个数组,编写一个函数来计算它们的交集。 不允许重复的元素出现在最终结果中。

class Solution { public int[] intersection(int[] nums1, int[] nums2) { Set<Integer> union = new HashSet<>(); Arrays.sort(nums1); Arrays.sort(nums2); // 设置两个指针 i和j 其中i指向nums1中的元素,j指向nums2中的元素 int i = 0; int j = 0; //只要两个nums还没有被遍历完,就继续便利 while(i < nums1.length && j < nums2.length){ // 如果指向的元素相同,则将元素添加到union中 if(nums1[i] == nums2[j]){ union.add(nums1[i]); i++; j++; } // 如果指向的元素不相同,则移动指针 else{ // 这时候移动指针也分为两种情况,第一种是nums1[i] > nums2[j] if(nums1[i] > nums2[j]) j++; else i++; } } int[] res = new int[union.size()]; int index = 0; for(int k:union) res[index++] = k; return res; } }

350 两个数组的交集2

题目:给定两个数组,编写一个函数来计算它们的交集。 允许重复的元素出现在最终结果中。

class Solution { public int[] intersect(int[] nums1, int[] nums2) { List<Integer> union = new ArrayList<>(); Arrays.sort(nums1); Arrays.sort(nums2); // 设置两个指针 i和j 其中i指向nums1中的元素,j指向nums2中的元素 int i = 0; int j = 0; //只要两个nums还没有被遍历完,就继续便利 while(i < nums1.length && j < nums2.length){ // 如果指向的元素相同,则将元素添加到union中 if(nums1[i] == nums2[j]){ union.add(nums1[i]); i++; j++; } // 如果指向的元素不相同,则移动指针 else{ // 这时候移动指针也分为两种情况,第一种是nums1[i] > nums2[j] if(nums1[i] > nums2[j]) j++; else i++; } } int[] res = new int[union.size()]; for(int k = 0;k<union.size();k++) res[k] = union.get(k); return res; } }

844 比较含退格的字符串

题目:给定 S 和 T 两个字符串,当它们分别被输入到空白的文本编辑器后,判断二者是否相等,并返回结果。 # 代表退格字符。

// 虽然是可以用双指针来写这道题,不过相对而言,使用额外的数据结构更容易理解以及更容易实现。使用stack class Solution { public boolean backspaceCompare(String S, String T) { return toString(S).equals(toString(T)); } public String toString(String str){ Stack<Character> stack = new Stack<>(); for(Character c:str.toCharArray()){ if(c=='#' && !stack.isEmpty()) stack.pop(); else if(c=='#') continue; else{ stack.push(c); } } String res = ""; while(!stack.isEmpty()) res+=stack.pop(); return res; } }

925 长键按入

题目:你的朋友正在使用键盘输入他的名字 name。偶尔,在键入字符 c 时,按键可能会被长按,而字符可能被输入 1 次或多次。你将会检查键盘输入的字符 typed。如果它对应的可能是你的朋友的名字(其中一些字符可能被长按),那么就返回 True。

class Solution { public boolean isLongPressedName(String name, String typed) { // 设置两个指针,i,j 其中i指针指向的是name中的字符,j指针指向的是typed中的字符 int i = 0; int j = 0; // 只要typed还有字符,就一直向后遍历 while(j<typed.length()){ // 如果i指针指向的name中的字符与j指针指向的typed中字符相同的话,两个指针均向后移动 if(i<name.length()&&name.charAt(i) == typed.charAt(j)){ i++; j++; }else if(j>0 && typed.charAt(j) == typed.charAt(j-1)){ //如果i指针指向的name中的字符与j指针指向的typed中的字符不相等并且typed中的j指向的字符与上一个j-1指向的字符相同, j++; }else{ return false; } } return i == name.length(); } }

977. 有序数组的平方

给定一个按非递减顺序排序的整数数组 A,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。

class Solution { public int[] sortedSquares(int[] A) { // 循环便利,将A中的元素替换成为原是数子的平方 for(int i =0;i<A.length;i++) A[i] = A[i]*A[i]; quickSort(A,0,A.length-1); return A; } // 手动实现快速排序 public void quickSort(int[] nums,int l,int r){ if(l<r){ int i = l; // 选取基准值 int pivot = nums[l]; int j = r; while(i<j){ // 从右到左找到比pivot小的值 while(i<j && nums[j]>=pivot) j--; // 找到了比pivot小的值,按照快速排序的思想,该值应该出现在基准值的左边,所以交换位置 if(i<j) nums[i] = nums[j]; // 从左到右找到比pivot大的值 while(i<j && nums[i]<=pivot) i++; if(i<j) nums[j] = nums[i]; } //交换完之后,将pivot放到他本来应该在的位置 nums[i] = pivot; // 然后递归处理基准值左边的以及基准值右边的子数列 quickSort(nums,l,i-1); quickSort(nums,i+1,r); } } }

剑指 Offer 04. 二维数组中的查找

在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

class Solution { public boolean findNumberIn2DArray(int[][] matrix, int target) { // 从数组的右上角开始查找,如果当前元素比target小就向下移动,如果当前元素比target大就向左移动 if(matrix.length == 0 || matrix == null) return false; // 获取matrix的行数和列数 int m = matrix.length; int n = matrix[0].length; // 设计两个指针,i和j 其中i指向当前所在的行数,j指向当前所在的列数,初始化i=0,j=n-1 int i = 0; int j = n-1; while(j>-1 && i<m){ if(matrix[i][j] > target) j--; else if(matrix[i][j] < target) i++; else return true; } return false; } }

剑指 Offer 22. 链表中倒数第k个节点

/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public int kthToLast(ListNode head, int k) { // 因为题目中说了k保证是有效的,所以不用先计算整个链表的长度 // 定义两个指针,一个快指针,一个慢指针,快指针在满指针后k个,当快指针为空的时候,满指针就到了目的元素的位置 ListNode slow = head; ListNode fast = head; while(k-->0) fast = fast.next; while(fast!=null){ slow = slow.next; fast = fast.next; } return slow.val; } }

面试题 02.02. 返回倒数第 k 个节点

实现一种算法,找出单向链表中倒数第 k 个节点。返回该节点的值。

/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public int kthToLast(ListNode head, int k) { // 因为题目中说了k保证是有效的,所以不用先计算整个链表的长度 // 定义两个指针,一个快指针,一个慢指针,快指针在满指针后k个,当快指针为空的时候,满指针就到了目的元素的位置 ListNode slow = head; ListNode fast = head; while(k-->0) fast = fast.next; while(fast!=null){ slow = slow.next; fast = fast.next; } return slow.val; } }

面试题 10.01. 合并排序的数组

给定两个排序后的数组 A 和 B,其中 A 的末端有足够的缓冲空间容纳 B。 编写一个方法,将 B 合并入 A 并排序。初始化 A 和 B 的元素数量分别为 m 和 n。

class Solution { public void merge(int[] A, int m, int[] B, int n) { // 一看就是倒着来嘛 int aLen = A.length-1; // 设置两个指针分别指向A,B中的元素,i指向A,j指向B int i = m-1; int j = n-1; while(i>-1 && j>-1){ if(A[i] > B[j]){ A[aLen] = A[i]; aLen--; i--; }else{ A[aLen] = B[j]; aLen--; j--; } } while(i>-1){ A[aLen] = A[i]; aLen--; i--; } while(j>-1){ A[aLen] = B[j]; aLen--; j--; } } }
最新回复(0)