import java.util.LinkedList;
public class FindInteger {
/**
* 编程之美 找符合条件的整数 用字符串来表示大整数避免溢出
* 题目:任意给定一个正整数N,求一个最小的正整数M(M>1),使得N*M的十进制表示形式里只含有1和0
*
* 假设当前正在搜索由0,1组成的K位十进制数,这样的K位十进制数共有2^k个。
* 假设其中有两个数X、Y,它们模N同余,那么在搜索由0、1组成的K+1位十进制数时,
* X和Y会被扩展出四个数:10X, 10X+1, 10Y, 10Y+1。
* 因为X和Y同余(同余完全可以看作相等),所以10X与10Y同余,10X+1与10Y+1同余。
* 也就是说由Y扩展出来的子树和由X扩展产生出来的子树产生完全相同的余数,
* 如果X比Y小,那么Y肯定不是满足要求的最小的数,所以Y这棵子树可以被剪掉
*/
public static void main(String[] args) {
/*测试发现,在i=36时,方法一和方法二已经出错了
for(int i=1;i<=36;i++){
System.out.println(i+"-------------------");
System.out.println(find3(i));
System.out.println(find2(i));
System.out.println(find(i));
}
*/
for(int i=1;i<Integer.MAX_VALUE;i++){
System.out.println("("+find3(i)+" mod "+i+")=0");
}
}
/*
* 方法三:对方法二的改进
* 用字符串来表示大整数,避免溢出
* 难点在于,如何由X求得(10*X)以及(10*X+1)对n的余数:
* if X%n=q, X=n*K+q
* then (10*X)%n=(10*n*K+10*q)%n=(10*q)%n
*/
public static String find3(int n){
if(n<=0){
return null;
}
if(n==1){
return "1";
}
String[] data=new String[n]; //data[i]代表(x%n=i)的x,x用字符串表示:"1101" --> int x=1101
data[1]="1";
int k=2;
while(true){ //不必担心这是个死循环,可以证明,M是一定存在的
for(int i=0;i<n;i++){
String di=data[i];
if(di==null){
continue;
}
int len=di.length();
if((len+1)==k){ //K-->K+1
String s=di+"0"; //di*10
String t=di+"1"; //di*10+1
int rs=(i*10)%n; //(di*10)%n=(i*10)%n
int rt=(i*10+1)%n; //(di*10+1)%n=(i*10+1)%n
if(rs==0){
return s;
}else if(data[rs]==null || greaterThan(data[rs],s)){ //只保留最小的data[i]
data[rs]=s;
}
if(rt==0){
return t;
}else if(data[rt]==null || greaterThan(data[rt],t)){
data[rt]=t;
}
}
}
k++;
}
}
/*
* 比较由s和t代表的数字的大小。按位比较,从高位到低位。
* 如果s比t大,返回true,否则返回false
*/
public static boolean greaterThan(String s,String t){
if(!s.matches("[0-9]+") || !t.matches("[0-9]+")){
return false;
}
if(s.length()!=t.length()){
return s.length()>t.length();
}
int len=s.length();
char[] ss=s.toCharArray();
char[] tt=t.toCharArray();
for(int i=0;i<len;i++){
if(ss[i]!=tt[i]){
return ss[i]>tt[i];
}
}
return false;
}
//方法一:因为N*M的取值就是1,10,11,100,101,110,111,......所以直接在这个空间搜索
public static int find(int n){
if(n<=0){
return -1;
}
if(n==1){
return 1;
}
LinkedList<Integer> queue=new LinkedList<Integer>();
queue.add(1);
while(!queue.isEmpty()){
int t=queue.pollFirst(); //Retrieves and removes
if(t%n==0){
return t;
}
queue.addLast(t*10);
queue.addLast(t*10+1);
}
return -1;
}
//方法二:将方法一的搜索空间按模N余数分类,但没有解决N*M超出Integer.MAX_VALUE的溢出问题
public static int find2(int n){
if(n<=0){
return -1;
}
if(n==1){
return 1;
}
int[] data=new int[n];
data[1]=1;
int k=2;
while(true){
for(int i=0;i<n;i++){
int di=data[i];
if(di==0){
continue;
}
int len=0;
int dii=di;
while(dii!=0){ //计算是几位整数。计算K+1位时只需考虑K位
dii /=10;
len++;
}
if((len+1)==k){
int s=di*10;
int t=di*10+1;
if(s%n==0){
return s;
}else if(data[s%n]==0 || data[s%n]>s){
data[s%n]=s;
}
if(t%n==0){
return t;
}else if(data[t%n]==0 || data[t%n]>t){
data[t%n]=t;
}
}
}
k++;
}
}
}
分享到:
相关推荐
整数转字符串的过程主要是将十进制整数转换为其对应的ASCII码表示。一个整数可以分为正负号、整数部分和小数部分。对于非负整数,我们从高位到低位逐位处理,将其转换为对应的字符。例如,数字"123"在ASCII码中的...
在本文中,我们将深入探讨如何使用C语言实现超长整数字符串的相加操作。超长整数是指那些超过了标准整型(如int、long long)所能表示范围的整数,通常出现在大数运算或者加密算法中。由于C语言本身并不支持这样的...
在编程领域,将整数转换为字符串是一项基本操作,它广泛应用于各种场景,如日志记录、用户界面显示以及网络通信。在C语言中,由于其底层特性,没有内置的直接转换函数,因此程序员需要手动实现这样的功能。本篇文章...
这些函数在处理字符串时非常实用,但使用时要注意防止缓冲区溢出。 此外,动态内存分配(如`new`关键字)和指针数组也是本课程可能涵盖的内容。指针数组允许你存储一组指针,每个指针可以指向不同的数组或字符串。...
C/C++语言本身并没有专门的字符串变量类型,而是使用字符数组来存放字符串,其中字符串的结束符是“\0”(空字符)。掌握字符与数字之间的转换对于进行有效编程至关重要,尤其在处理用户输入、数据输出以及与其他...
在C++编程中,字符串转换为整数是一个常见的任务,特别是在处理用户输入或者解析数据时。LeetCode第8题正是关于这个主题,它要求我们实现一个函数`atoi()`,将给定的字符串转换为对应的整数值。在此题解中,我们将...
在计算机二级C语言考试中,理解和掌握如何将只包含数字的字符串转换为整数是一项重要的技能。这涉及到C语言中的字符串处理和类型转换知识。在本篇内容中,我们将深入探讨这一主题,以便帮助你更好地准备计算机二级...
对于溢出检查,C语言默认不做任何处理,因此在处理大整数时需要额外的逻辑来确保结果在整数范围之内。 3. **整数比较**:使用`, `>`, `, `>=`, `==`, `!=`这些比较运算符,我们可以轻松地对两个整数进行大小判断。...
总之,在VC++环境下,处理任意长度字符串整数的加减乘除运算需要深入理解大整数的表示和运算原理,结合C++的特性来设计和实现高效的数据结构和算法。这不仅提升了编程能力,也为解决实际问题提供了强大的工具。
把一个字符串转化为相应的整数。特别注意符号与溢出的问题。
在C#编程语言中,字符串转换为整数是常见的操作,尤其在处理用户输入或者解析数据时。这个过程可以通过内置的`int.Parse()`、`int.TryParse()`、`Convert.ToInt32()`等方法来完成。然而,为了更好地理解底层机制和...
使用字符串解决c++中大整数加减法运算的问题,从而防止溢出。
字符串是编程语言中常见且重要的数据结构之一,尤其在面试中常常被用来考察候选人的逻辑思维和算法理解能力。以下是一些与字符串相关的面试题目及其解题思路: 1. **字符串循环左移**:给定一个字符串和一个整数k,...
- 大数处理:使用ulong类型来处理大数值,避免了整型溢出问题。 代码中实现的算法逻辑可以概括为: 1. 通过字符串拼接操作将两个给定的字符串以特定的顺序(例如"BA")进行无限次拼接,直到达到特定的长度n。这一...
当我们自定义这些函数时,还需要考虑到安全问题,比如确保目标字符串有足够的空间容纳源字符串,避免缓冲区溢出。这通常需要在复制或替换前计算字符串长度,并进行适当检查。 7. **性能优化**: 自定义字符串函数...
这些类型的数据在内存中以二进制形式存储,而字符串则是以字符数组的形式存在,每个字符用ASCII码表示。将整型转换为字符串,我们需要借助一些特定的函数或自定义的代码。 1. 标准库函数itoa:虽然C标准库并未提供...
在 Wincc 中,用户可以使用C语言的函数来处理字符串,这对于数据处理和显示非常有用。以下是对文档中提到的四个字符串相关函数的详细说明: 1. **strcpy()**:这个函数用于拷贝一个字符串到另一个字符串。在示例中...
使用递归来实现字符串反转,递归结束条件为字符串结束标志'\0',从后往前打印字符,从而达到反转的效果。 #### 2. 字符串复制 - strcpy `strcpy`函数用于将一个字符串复制到另一个字符串中。在C语言标准库中,`...
### C语言基础字符串知识点概述 #### 一、函数调用方式 在C语言中,函数调用有两种主要的方式:传值调用和传址...这些知识点对于学习C语言的初学者来说至关重要,能够帮助他们更好地理解和掌握字符串相关的编程技巧。
同时,我们通过比较当前结果和溢出边界来防止整数溢出。 在实际面试中,除了提供解决方案,还应考虑代码的效率、可读性以及异常处理。例如,可能需要添加对空指针、空字符串等特殊情况的处理。此外,了解并讨论其他...