剑指Offer面试题14使数组中的奇数在偶数前,面试题15链表倒数第k个结点

面试题14:使数组中奇数位于偶数前

输入一个整数数组,实现一个函数来调整数组中的数字的顺序,使得所有奇数位于数组的前半部分,偶数位于后半部分。

思路:前后各一个指针相互靠近,如果前偶后奇,交换位置,直到两个指针相遇。复杂度O(n)。

注意:如果题目换成负数在正数前边,或能被3整除的在不能的前边等,只是判断条件改变,所以我们把判断功能分离出来,每次只修改这个功能就行了。

本题Java实现:

public class Reorder {
	static boolean yesOrNo(int number){//是不是偶数
		boolean tag = true;//是偶数返回真
		if( (number & 1) == 1 ){//是奇数返回假
			tag = false;
		}
		return tag;
	}
	static void reorder(int[] array){
		if(array.length == 0){
			System.out.println("数组为空");
			return;
		}
		int left = 0;
		int right = array.length - 1;//前后各一个指针
		while(left < right){
			while( (left < right) && !yesOrNo(array[left]) ){//跳过前边的奇数
				left++;
			}
			while( (left < right) && yesOrNo(array[right]) ){//跳过后边的偶数
				right--;
			}
			if(left < right){//交换
				int temp = array[right];
				array[right] = array[left];
				array[left] = temp;
			}
		}
	}
	public static void main(String[] args) {
		int[] test = {2,4,5,6,1,3,9};
		reorder(test);
		System.out.println(Arrays.toString(test));
	}
}

面试题15:链表中倒数第K个结点

输入一个单链表,输出该链表中倒数第k个结点。链表的尾结点是倒数第1个结点。例如一个链表有4个结点,依次是1,2,3,4,这个链表的倒数第3个结点是2。

思路1:假设链表有n个结点,那么倒数第k个结点就是从头开始的第n-k+1个结点。所以一种方法是遍历两次链表,第一次得到n,第二次找到k。

思路2:更好的方法是只需遍历一次,我们定义两个指针,第一个指针从头开始走k-1步,从第k步开始,第二个指针也开始从头开始走,两个指针的距离为k-1,当第一个指针到达尾结点时,第二个指针刚好在倒数第k个。

相关题1:求链表的中间结点。如果是结点数是偶数,返回中间两个任意一个。也可以用两个指针,一个指针一次走一步,另一个走两步,走得快的到末尾时,走得慢的刚好在中间结点。

相关题2:判断单链表是否形成环形结构。还是一个指针走一步,一个指针走两步,走得快的指针如果追上走得慢的指针,那么就是环形的。如果走得快的走到了末尾都没有追上,说明不是环形。

本题的Java实现:

class ListNode{
	int value;
	ListNode next;
	ListNode(int x){
		value = x;
		next = null;
	}
}
public class FindKthToTail {
	//头插法建立链表,这里假设头结点就是第一个结点。
	private ListNode insertFirst(){
		Scanner sc = new Scanner(System.in);
		ListNode headNode = null;
		System.out.println("输入链表值,以0结束:");
		int input = sc.nextInt();
		while(input != 0){
			ListNode p = new ListNode(input);
			p.next = headNode;
			headNode = p;
			input = sc.nextInt();
		}
		return headNode;
	}
	//正序打印链表
	private void print(ListNode headNode){
		if(headNode == null){
			System.out.println("打印方法的输入为空");
			return;
		}
		while(headNode != null){
			System.out.println(headNode.value);
			headNode = headNode.next;
		}
	}
	//找到倒数第k个
	private ListNode find(ListNode headNode, int k){
		if(headNode == null || k <= 0){
			System.out.println("输入为空或k有误");
			return null;
		}
		ListNode p1 = headNode;
		ListNode p2 = headNode;
		for(int i=0;i<k-1;i++){//p1先走k-1步
			if(p1.next != null){
				p1 = p1.next;
			}else{
				System.out.println("输入k有误");
				return null;
			}
		}
		while(p1.next != null){
			p1 = p1.next;
			p2 = p2.next;
		}
		return p2;
	}
	public static void main(String[] args) {
		FindKthToTail test = new FindKthToTail();
		ListNode ln = test.insertFirst();
		test.print(ln);
		System.out.println("请输入k:");
		Scanner sc = new Scanner(System.in);
		int k = sc.nextInt();
		System.out.println("倒数第"+k+"个是:" + test.find(ln,k).value);
		sc.close();
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值