剑指Offer面试题12打印1到最大的n位数,面试题13在O(1)时间删除链表结点

面试题12:打印1到最大的n位数

输入数字n,按顺序打印出从1最大的n位十进制数。例如输入3,则打印出1,2,3,...,一直到最大的3位数即999。

注意:没有限定n的范围时,注意大数问题,n可能会超出基本数值类型的表示范围,此时可以用字符串来表示,每一位上都是0-9的遍历,可以用递归。

题外话:Java中有两个类BigInteger和BigDecimal分别表示大整数类和大浮点数类,理论上能表示无限大的数。

本题利用字符串和递归方法的Java实现:

public class Print1ToMaxOfNDigits {
	private void print(String str,int len){
        if (len == 0) {//递归结束条件
        	for(int j = 0;j < str.length();j++){//不输出字符串前边的0
        		if(str.charAt(j) != '0'){
        			System.out.println(str.substring(j));
        			break;
        		}
        	}
            return;
        }
        for (int i = 0; i < 10; i++) {
            print(str + i,len - 1);
            //递归说明:程序先第一次进入循环体,进入第一层递归输入是(0,1),不满足递归结束条件,然后第二次进入循环体,再进入第二层递归输入是(00,0),满足结束条件输出00,
            //然后回到第二次进入的循环体中,执行循环体的第二轮,会进入新的第二层递归输入是(01,0),满足结束条件输出01,以此类推,直到09,这个循环体结束,
            //此时第一层递归结束,程序开始执行第一次进入的循环体的第二轮,会进入新的第一层递归,输入是(1,1),以此类推。
        }
    }
    private void print1ToMaxOfDigits(int n) {
    	if(n <= 0){
    		System.out.println("输入有误");
    		return;
    	}
        print("", n);
    }
    public static void main(String[] args) {
        Print1ToMaxOfNDigits test=new Print1ToMaxOfNDigits();
        test.print1ToMaxOfDigits(2);
    }
}

面试题13:在O(1)时间删除链表结点

给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点。

思路:一般思路是从头开始遍历,这样复杂度是O(n)不合题意。我们的方法是把该节点的值设为该节点下一个节点的值,然后让该节点指向下下一个节点。

这样会有三种情况:1,要删除的节点不是尾节点。2,链表只有一个节点3,要删除的节点是尾节点,只能从头到尾遍历了。最后平均一下复杂度还是O(1)。

本题的Java实现:

class ListNode{
	int value;
	ListNode next;
	ListNode(int x){
		value = x;
		next = null;
	}
}
public class DeleteNode {
	static void delete(ListNode headNode,ListNode toBeDeleted){
		if(headNode == null || toBeDeleted == null){
			System.out.println("都是null");
			return;
		}
		if(toBeDeleted.next != null){//1,要删除的节点不是尾节点
			toBeDeleted.value = toBeDeleted.next.value;
			toBeDeleted.next = toBeDeleted.next.next;
		}else if(headNode.next == toBeDeleted){//2,链表只有一个节点,要把头指针设为NULL。
			headNode.next = null;
		}else{//3,要删除的节点是尾节点
			while(headNode.next != toBeDeleted){
				headNode = headNode.next;
			}
			headNode.next = null;
		}
	}
	public static void main(String[] args){
		ListNode head = new ListNode(0);
		ListNode one = new ListNode(1);
		ListNode two = new ListNode(2);
		head.next = one;
		one.next = two;
		delete(head, one);
		while(head != null){
			System.out.println(head.value);
			head = head.next;
		}
	}
}

本题的C语言实现:

void delete_node(plist &headnode,plist pdele){ //参数是头结点和要删除的节点
	if(headnode == NULL || pdele == NULL) return;
	//要删除的节点不是尾节点
	if(pdele->next != NULL){
		plist pnext = pdele->next;
		pdele->data = pnext->data;
		pdele->next = pnext->next;
		free(pnext);
	}else if(pdele == headnode){//链表只有一个节点,删除头结点(也是尾节点)
		free(pdele);
		headnode = NULL;
	}else{//链表中有多个节点,删除尾节点
		plist pnode = headnode;
		while(pnode->next != pdele){
			pnode = pnode->next;
		}
		pnode->next = NULL;
		free(pdele);
	}
}
调用:delete_node(head,delenode);

注意:有关指针传参可参看剑指Offer面试题5反向打印链表的c实现。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值