两个链表的第一个公共结点,数字在排序数组中出现的次数

题目描述
在这里插入图片描述
解题思路
设 A 的长度为 a + c,B 的长度为 b + c,其中 c 为尾部公共部分长度,可知 a + c + b = b + c + a。
当访问链表 A 的指针访问到链表尾部时,令它从链表 B 的头部重新开始访问链表 B;同样地,当访问链表 B 的指针
访问到链表尾部时,令它从链表 A 的头部重新开始访问链表 A。这样就能控制访问 A 和 B 两个链表的指针能同时访
问到交点。

	public ListNode findFirstCommonNode(ListNode node1,ListNode node2) {
		ListNode l1=node1;
		ListNode l2=node2;
		while(l1!=l2) {
			l1=(l1==null)?node2:l1.next;
			l2=(l2==null)?node1:l2.next;
		}
		return l1;
	}

我们还可以借助栈来完成。先把两个链表依次装到两个栈中,然后比较两个栈的栈顶结点是否相同,如果相同则出栈,如果不同,那最后相同的结点就是我们要的返回值。

	// 利用栈的方法
	public ListNode findFirstCommonNodeByStack(ListNode node1, ListNode node2) {
		Stack<ListNode> stack1 = new Stack<>();
		Stack<ListNode> stack2 = new Stack<>();
		if (node1 != null) {
			stack1.push(node1);
			node1 = node1.next;
		}
		if (node2 != null) {
			stack2.push(node2);
			node2 = node2.next;
		}
		ListNode node=null;
		if(!stack1.isEmpty()&&!stack2.isEmpty()&&stack1.peek()==stack2.peek()) {
			stack1.pop();
			node=stack2.pop();
		}
		return node;
	}

题目描述
统计一个数字在排序数组中出现的次数。
Input: nums = 1, 2, 3, 3, 3, 3, 4, 6
K = 3 Output: 4
解题思路
通过二分查找,找到k的第一个开始下标和最后一个的下标

//利用二分查找的方法
	public int getNumberTime(int[] nums, int k) {
		int len = nums.length;
		if (len == 0) {
			return 0;
		}
		int first = getFirst(nums, k, 0, len - 1);
		int last = getLast(nums, k, 0, len - 1);
		if (first != -1 && last != -1) {
			return last - first + 1;
		}
		return 0;
	}

	private int getLast(int[] nums, int k, int start, int end) {
		int mid;
		while (start <= end) {
			mid = start + (end - start) / 2;
			if (k >= nums[mid]) {
				start = mid + 1;
			} else {
				end = mid - 1;
			}
		}
		if (end >= 0 && nums[end] == k) {
			return end;
		}

		else {
			return -1;
		}
	}

	private int getFirst(int[] nums, int k, int start, int end) {
		int mid;
		while (start <= end) {
			mid = start + (end - start) / 2;
			if (k <= nums[mid]) {
				end = mid - 1;
			} else {
				start = mid + 1;
			}
		}
		if (start < nums.length && nums[start] == k) {
			return start;
		} else {
			return -1;
		}
	}

优化版本的二分查找

	//优化版本的通过二分查找
	public int getNumberTime1(int[] nums,int k){
		int first=binarySearch(nums, k);
		int last=binarySearch(nums,k+1);
		return (first==nums.length||nums[first]!=k)?0:last-first;
	}
	private int binarySearch(int[] nums, int k) {
		int start=0;
		int end=nums.length;
		while(start<end) {
			int m=start+(end-start)/2;
			if(nums[m]>=k) {
				end=m;
			}else {
				start=m+1;
			}
		}
		return start;
	}

我们还可以通过k+0.5,k-0.5,直接搜索k-0.5和k+0.5这两个数应该插入的位置,然后相减即可。

//直接搜索k-0.5和k+0.5这两个数应该插入的位置,然后相减即可。
	public int getNumberTime2(int[] nums, int k) {
		return binarySearch(nums, k + 0.5) - binarySearch(nums, k - 0.5);
	}

	private int binarySearch(int[] nums, double k) {
		int start = 0;
		int end = nums.length ;
		while(start<=end) {
			int m=start+(end-start)/2;
			if(nums[m]>k) {
				end=m-1;
			}else {
				start=m+1;
			}
		}
		return start;
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值