剑指offer:50-53记录

举报
兔老大 发表于 2021/04/24 00:20:59 2021/04/24
【摘要】 在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 示例: s = "abaccdeff" 返回 "b" s = ""  返回 " "   限制: 0 <= s 的长度 <= 50000 思路:map记录次数,再次遍历找出次数1的。 class Solution { public char firstUniqC...

在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。

示例:

s = "abaccdeff"
返回 "b"

s = "" 
返回 " "
 

限制:

0 <= s 的长度 <= 50000

思路:map记录次数,再次遍历找出次数1的。


  
  1. class Solution {
  2. public char firstUniqChar(String s) {
  3. // 哈希表存储,<字符,出现次数>
  4. Map<Character,Integer> map=new HashMap<>();
  5. for(int i=0;i<s.length();i++){
  6. if(map.containsKey(s.charAt(i))){
  7. map.put(s.charAt(i),map.get(s.charAt(i))+1);
  8. }else{
  9. map.put(s.charAt(i),1);
  10. }
  11. }
  12. //顺序判断,只要找到第一个出现次数为1的就返回
  13. for(int i=0;i<s.length();i++){
  14. if(map.get(s.charAt(i))==1)
  15. return s.charAt(i);
  16. }
  17. return ' ';
  18. }
  19. }

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。

示例 1:

输入: [7,5,6,4]
输出: 5

归并加一句统计。


  
  1. class Solution {
  2. private int res;
  3. public int reversePairs(int[] nums) {
  4. if (nums == null || nums.length < 1) {
  5. return 0;
  6. }
  7. mergeSort(nums, 0, nums.length - 1);
  8. return res;
  9. }
  10. private void mergeSort(int[] arr, int left, int right) {
  11. if (left == right) {
  12. return;
  13. }
  14. int mid = (left + right) >>> 1;
  15. mergeSort(arr, left, mid);
  16. mergeSort(arr, mid + 1, right);
  17. merge(arr, left, mid, right);
  18. }
  19. private void merge(int[] arr, int left, int mid, int right) {
  20. int[] temp = new int[right - left + 1];
  21. int i = left, j = mid + 1, index = 0;
  22. while (i <= mid && j <= right) {
  23. if (arr[i] <= arr[j]) {
  24. temp[index++] = arr[i++];
  25. } else {
  26. temp[index++] = arr[j++];
  27. //加一句
  28. res += mid - i + 1;
  29. }
  30. }
  31. while (i <= mid) {
  32. temp[index++] = arr[i++];
  33. }
  34. while (j <= right) {
  35. temp[index++] = arr[j++];
  36. }
  37. System.arraycopy(temp, 0, arr, left, temp.length);
  38. }
  39. }

如果两个链表没有交点,返回 null.
在返回结果后,两个链表仍须保持原有的结构。
可假定整个链表结构中没有循环。
程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。

思路:先都走到最后,顺便统计长度。

结尾不一样就肯定没有相交,返回。

然后让长的先几步,走到一样长了再一起往前走,相遇就找到了。


  
  1. /**
  2. * Definition for singly-linked list.
  3. * public class ListNode {
  4. * int val;
  5. * ListNode next;
  6. * ListNode(int x) {
  7. * val = x;
  8. * next = null;
  9. * }
  10. * }
  11. */
  12. public class Solution {
  13. public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
  14. if(headB==null || headA==null){
  15. return null;
  16. }
  17. ListNode tempA=headA;
  18. ListNode tempB=headB;
  19. int a=0;
  20. int b=0;
  21. while(tempA.next!=null){
  22. tempA=tempA.next;
  23. a++;
  24. }
  25. while(tempB.next!=null){
  26. tempB=tempB.next;
  27. b++;
  28. }
  29. if(tempB!=tempA){
  30. return null;
  31. }
  32. tempA=headA;
  33. tempB=headB;
  34. if(a>b){
  35. for(int i=0;i<a-b;i++){
  36. tempA=tempA.next;
  37. }
  38. }else{
  39. for(int i=0;i<b-a;i++){
  40. tempB=tempB.next;
  41. }
  42. }
  43. while(tempB!=tempA){
  44. tempA=tempA.next;
  45. tempB=tempB.next;
  46. }
  47. return tempA;
  48. }
  49. }

统计一个数字在排序数组中出现的次数。

示例 1:

输入: nums = [5,7,7,8,8,10], target = 8
输出: 2
示例 2:

输入: nums = [5,7,7,8,8,10], target = 6
输出: 0
 

限制:

0 <= 数组长度 <= 50000

思路:两次二分,稍微修改一下查最左或最右。最后相减即可。


  
  1. class Solution {
  2. public int search(int[] nums, int target) {
  3. int left=searchRangeLeft(nums,target);
  4. int right=searchRangeRight(nums,target);
  5. if(left==-1)return 0;
  6. return right-left+1;
  7. }
  8. public int searchRangeLeft(int[] nums, int target) {
  9. int left=0;
  10. int right=nums.length-1;
  11. while(left<=right){
  12. int mid=(left+right)/2;
  13. if(nums[mid]>target){
  14. right=mid-1;
  15. }else if(nums[mid]<target){
  16. left=mid+1;
  17. }else if(mid==0 || nums[mid-1]!=target){
  18. return mid;
  19. }else{
  20. right=mid-1;
  21. }
  22. }
  23. return -1;
  24. }
  25. public int searchRangeRight(int[] nums, int target) {
  26. int left=0;
  27. int right=nums.length-1;
  28. while(left<=right){
  29. int mid=(left+right)/2;
  30. if(nums[mid]>target){
  31. right=mid-1;
  32. }else if(nums[mid]<target){
  33. left=mid+1;
  34. }else if(mid==nums.length-1 || nums[mid+1]!=target){
  35. return mid;
  36. }else{
  37. left=mid+1;
  38. }
  39. }
  40. return -1;
  41. }
  42. }

一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。

 

示例 1:

输入: [0,1,3]
输出: 2
示例 2:

输入: [0,1,2,3,4,5,6,7,9]
输出: 8
 

限制:

1 <= 数组长度 <= 10000

思路1:异或,就一个没出现的剩下了,别的两两抵消了。


  
  1. class Solution {
  2. public int missingNumber(int[] nums) {
  3. int res=nums.length;
  4. for(int i=0;i<nums.length;i++){
  5. res^=nums[i];
  6. res^=i;
  7. }
  8. return res;
  9. }
  10. }

思路2:二分,条件就是值是否等于下标。


  
  1. class Solution {
  2. public int missingNumber(int[] nums) {
  3. int left = 0;
  4. int right = nums.length-1;
  5. while(left<=right){
  6. int mid = (left+right) / 2;
  7. if(nums[mid]!=mid) right = mid -1;
  8. else left = mid + 1;
  9. }
  10. return left;
  11. }
  12. }

 

文章来源: fantianzuo.blog.csdn.net,作者:兔老大RabbitMQ,版权归原作者所有,如需转载,请联系作者。

原文链接:fantianzuo.blog.csdn.net/article/details/104777859

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。